JDK 1.1 for Solaris Developer's Guide

Programming Compute-Bound, Parallellized Java Applications

Caution - Caution -

In general, avoid using a native method to access Solaris-specific functionality such as thr_setconcurrency(3THR), since the application is then tied to the Solaris environment and is no longer 100% Pure Java.

Note -

Most Java applications do not need to use thr_setconcurrency(3THR). The only cases in which it might be necessary would be, for instance, a demo with dummy threads that spin interminably or a compute-bound application such as matrix multiplication or a parallelized graphics computation.

thr_setconcurrency Example

A compute-bound application, such as parallelized matrix multiplication, must use a native method to call thr_setconcurrency(3THR). This insures that sufficient concurrency resources are available to the Java application to fully use multiple processors. This is not necessary for most Java applications and applets. The following code is an example of how to do this.

The first element is the Java application, MPtest.java, that will use MPtest_NativeTSetconc(). This application creates 10 threads, each of which displays an identifying line, then loops 10,000,000 times to simulate a compute-bound activity.

Example 3-3 MPtest.java

import java.applet.*;
import java.io.PrintStream;
import java.io.*;
import java.net.*;
class MPtest {
   static native void NativeTSetconc();
   static public int THREAD_COUNT = 10;
   public static void main (String args[]) {
      int i;
// set concurrency on Solaris - sets it to
// sysconf (_SC_ NPROCESSORS_ONLN)
// start threads
      client_thread clients[] = new client_thread[ THREAD_COUNT ];
      for ( i = 0; i < THREAD_COUNT; ++i ){
         clients[i] = new client_thread(i, System.out);
   static { System.loadLibrary("NativeThreads"); 
class client_thread extends Thread {
   PrintStream out;
   public int LOOP_COUNT = 10000000;
   client_thread(int num, PrintStream out){
      super( "Client Thread" + Integer.toString( num ) );
      this.out = out;
      out.println("Thread " + num);
   public void run () {
      for( int i = 0; i < this.LOOP_COUNT  ; ++i ) {;

The second element is the C stub file, MPtest.c, generated from MPtest.java by the utility javah(1). Enter

% javah -stubs MPtest.java

The third element is the C header file, MPtest.h, also generated from MPtest.java by the utility javah(1). Enter

% javah MPtest.java

The fourth element is the C function, NativeThreads.c, which performs the call to the C library interface.

#include <thread.h>
#include <unistd.h>
#include <jni.h>
JNIEXPORT void JNICALL Java_MPtest_NativeTSetconc(JNIEnv *env, jclass obj) {

Finally, combining the four files into the Java application, MPtest.class, is most easily done with a make(1S) file such as shown in Example 3-4.

Example 3-4 MPtest.class

# Make has to be done in two stages:
# first do "make MPtest"
# Then create NativeThreads.c to incorporate the native call
# to "thr_setconcurrency(_SC_NPROCESSORS_ONLN)"
# and then do "make lib".
# After this, you should be able to run "java MPtest" with LD_LIBRARY_PATH
# and CLASSPATH set to "."
JAVA_HOME=/usr/java JH_INC1=${JAVA_HOME}/include JH_INC2=${JAVA_HOME}/include/solaris
${JAVA_HOME}/bin/javac MPtest.java 
export CLASSPATH; 
${JAVA_HOME}/bin/javah MPtest)
export CLASSPATH; 
${JAVA_HOME}/bin/javah -jni MPtest)cc -G -I${JH_INC1} -I${JH_INC2} NativeThreads.c\
		 -lthread -o libNativeThreads.so
rm -rf *.class libNativeThreads.so NativeThreads.o *.h