Android* Tutorial: Writing a Multithreaded Application using Intel® Threading Building Blocks

By Vladimir Polin, Published: 12/12/2013, Last Updated: 12/12/2013

Recently we posted the “Windows* 8 Tutorial: Writing a Multithreaded Application for the Windows Store* using Intel® Threading Building Blocks”. There we stated that the parallel calculation engine can be ported easily to other mobile or desktop platforms. Android is a good example of such a mobile platform.

In a recently posted stable release of Intel Threading Building Blocks (Intel® TBB), we have added experimental support for Android applications; i.e., building Intel TBB libraries for use in Android applications via the JNI interface.  You can download this release from

To start the process on a Linux* host, unpack the Intel TBB source distribution, source the <unpacked_dir>/build/android_setup.csh script, and build the libraries.  Building the libraries is necessary because development releases are distributed in source form only. The <unpacked_dir>/build/ file contains instructions to configure the environment and build the library on Linux.

Assuming that gnu make 3.81 is available in the %PATH% (on a Microsoft Windows* host platform) and $PATH (on a Linux host) we need to issue the following command in the NDK environment to build the Intel TBB libraries for Android:

gmake tbb tbbmalloc target=android

That’s all that is needed for the library build; we can now move to build the example using Eclipse*. For the example below, I’ll use Android SDK Tools Rev.21 and Android NDK Rev 8C on Windows* to illustrate the process of cross-platform development.

Create a new project using a default template «New Android Application». For simplicity, we name it “app1”, the same as in the previous post:

Select FullscreenActivity as the Activity. That’s it for the template. Please note that com.example* is not an acceptable package naming for Google Play* but it is good enough for our example. 

Then add a couple of buttons to the main frame. After adding these, the XML file of the main frame (app1/res/layout/activity_fullscreen.xml) will look like this:

<FrameLayout xmlns:android=""     xmlns:tools=""     android:layout_width="match_parent"     android:layout_height="match_parent"     android:background="#0099cc"     tools:context=".FullscreenActivity" >     <TextView         android:id="@+id/fullscreen_content"         android:layout_width="match_parent"         android:layout_height="match_parent"         android:gravity="center"         android:keepScreenOn="true"         android:text="@string/dummy_content"         android:textColor="#33b5e5"         android:textSize="50sp"         android:textStyle="bold" />     <FrameLayout         android:layout_width="match_parent"         android:layout_height="match_parent"         android:fitsSystemWindows="true" >         <LinearLayout             android:id="@+id/fullscreen_content_controls"             style="?buttonBarStyle"             android:layout_width="match_parent"             android:layout_height="74dp"             android:layout_gravity="bottom|center_horizontal"             android:background="@color/black_overlay"             android:orientation="horizontal"             tools:ignore="UselessParent" >             <Button                 android:id="@+id/dummy_button1"                 style="?buttonBarButtonStyle"                 android:layout_width="0dp"                 android:layout_height="wrap_content"                 android:layout_weight="1"                 android:text="@string/dummy_button1"                 android:onClick="onClickSR" />             <Button                 android:id="@+id/dummy_button2"                 style="?buttonBarButtonStyle"                 android:layout_width="0dp"                 android:layout_height="wrap_content"                 android:layout_weight="1"                 android:text="@string/dummy_button2"                 android:onClick="onClickDR" />         </LinearLayout>     </FrameLayout> </FrameLayout>

And the string file (app1/res/values/strings.xml) will look like

<?xml version="1.0" encoding="utf-8"?> <resources>     <string name="app_name">Sample</string>     <string name="dummy_content">Reduce sample</string>     <string name="dummy_button1">Simple Reduce</string>     <string name="dummy_button2">Deterministic Reduce</string> </resources>

Then add buttons handlers:

// JNI functions private native float onClickDRCall(); private native float onClickSRCall();         public void onClickDR(View myView) {             TextView tv=(TextView)(this.findViewById(;             float res=onClickDRCall();             tv.setText("Result DR is n" + res);       }         public void onClickSR(View myView) {             TextView tv=(TextView)(this.findViewById(;             float res=onClickSRCall();             tv.setText("Result SR is n" + res);       }

and library loads to the file:

       @Override       protected void onCreate(Bundle savedInstanceState) {             super.onCreate(savedInstanceState); …             System.loadLibrary("gnustl_shared");             System.loadLibrary("tbb");             System.loadLibrary("jni-engine");              }

In the case of the "tbb" library everything should be clear, and the "gnustl_shared" library is required to support the C++ language features of TBB.   However, for the "jni-engine" library we need to go into more details.

"jni-engine" is a С++ library that implements a calculation engine and exports C-interfaces for JNI calls named onClickSRCall() and onClickSRCall().

According to NDK development rules, create folder “jni” inside the workspace and create 3 files there specific for our "jni-engine" library.

These files are: (text in <> brackets there is something that should be replaced with actual values)

LOCAL_PATH := $(call my-dir) TBB_PATH := <path_to_the_package>   include $(CLEAR_VARS) LOCAL_MODULE    := jni-engine LOCAL_SRC_FILES := jni-engine.cpp LOCAL_CFLAGS += -DTBB_USE_GCC_BUILTINS -std=c++11 -I$(TBB_PATH)/include LOCAL_LDLIBS := -ltbb -L./ -L$(TBB_PATH)/<path_to_libtbb_so> include $(BUILD_SHARED_LIBRARY)   include $(CLEAR_VARS) LOCAL_MODULE    := libtbb LOCAL_SRC_FILES := include $(PREBUILT_SHARED_LIBRARY)

APP_ABI := x86 APP_GNUSTL_FORCE_CPP_FEATURES := exceptions rtti APP_STL := gnustl_shared


 #include <jni.h>   #include "tbb/parallel_reduce.h" #include "tbb/blocked_range.h" float SR_Click() {     int N=10000000;     float fr = 1.0f/(float)N;     float sum = tbb::parallel_reduce(         tbb::blocked_range<int>(0,N), 0.0f,         [=](const tbb::blocked_range<int>& r, float sum)->float         {             for( int i=r.begin(); i!=r.end(); ++i )                 sum += fr;             return sum;         },         []( float x, float y )->float         {             return x+y;         }     );     return sum;   }   float DR_Click() {     int N=10000000;     float fr = 1.0f/(float)N;     float sum = tbb::parallel_deterministic_reduce(         tbb::blocked_range<int>(0,N), 0.0f,         [=](const tbb::blocked_range<int>& r, float sum)->float         {             for( int i=r.begin(); i!=r.end(); ++i )                 sum += fr;             return sum;         },         []( float x, float y )->float         {             return x+y;         }     );          return sum;   }    extern "C" JNIEXPORT jfloat JNICALL Java_com_example_app1_FullscreenActivity_onClickDRCall(JNIEnv *env, jobject obj) {     return DR_Click(); }   extern "C" JNIEXPORT jfloat JNICALL Java_com_example_app1_FullscreenActivity_onClickSRCall(JNIEnv *env, jobject obj) {     return SR_Click(); }

We use the same algorithms that we used in the previous blog.

When we use the NDK to build, it compiles libraries to the required folders including our libraries, and

Next, switch back to Eclipse and build the app1.apk file. Now the application is ready to install on AVD or actual hardware. On AVD it looks like


That’s it! This simple application is ready and should be a good start towards writing a more complex parallel application for Android. And for those who used code from the previous blog, the application was successfully ported to Android.

* Other names and brands may be claimed as the property of others.

Related Articles and Resources:

Product and Performance Information


Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors. These optimizations include SSE2, SSE3, and SSSE3 instruction sets and other optimizations. Intel does not guarantee the availability, functionality, or effectiveness of any optimization on microprocessors not manufactured by Intel. Microprocessor-dependent optimizations in this product are intended for use with Intel microprocessors. Certain optimizations not specific to Intel microarchitecture are reserved for Intel microprocessors. Please refer to the applicable product User and Reference Guides for more information regarding the specific instruction sets covered by this notice.

Notice revision #20110804