Previous Topic

Next Topic

Book Contents

Book Index

Thread Pool

This document describes how to work with a thread pool.

Auto-shrinking

After some time of work, idle threads in the pool may increase their number much above the minimum. That’s why an auto-shrinking mechanism is implemented – every 30 seconds (or the value of the mbs.util.threadpool.inactiveTime system property) the ThreadPoolManager service checks the threads in the pool and if needed reduces the idle threads number to the number of accessed threads within this time period. If accessed threads are less than the minimum, idle threads count is shrunk to the defined minimum.

Ways of Threads Allocation

The ThreadPoolManager service supports two approaches for allocating threads from the thread pool:

In both ways it becomes possible to avoid having all pool's threads allocated by a single bundle. The bundle is not allowed to take concurrently more threads than the number specified earlier to the ThreadPoolManager service. If the bundle requests a thread over the indicated limit, the request will wait until the bundle reduces consumed threads. Then, the job will be queued up in the pool of waiting jobs.

Executing a Runnable Job

A Runnable job can be executed within the thread pool by passing it in the corresponding execute method of the ThreadPoolManager instance either returned by the ThreadPoolFactoryservice or got as a service from the OSGi framework. The ThreadPoolManager service allows setting different priorities of its subordinate threads as well as, depending on the mbs.util.threadpool.useNames system property, naming each executed job.

The code example below contains two components:

The job is simple and common – in order to process an operation, it waits for an event to occur; if the event does not occur within a certain time period (1 second in the example), another operation is loaded. In the example below, the event is the turning on of the check flag and all operations are related to printing messages in the system output.

Listing 1. The Runnable Object example.

  public class RunnableTest implements Runnable {
        
    private Object synch;
    private boolean check;
          
    //Constructs a test job
    public RunnableTest() {
      check = false;
      synch = new Object();
    }
        
    //This method is executed by the Thread Pool Manager service
    public void run() {
      synchronized(synch) {    
        System.out.println("Job  "
                           + Thread.currentThread().getName()
                           + " starts running!");
        if (!check) {      
          try {        
            synch.wait(1000);      
           } catch (InterruptedException e) { }    
        }
        if (check) {      
          System.out.println("OK: CHECKED");    
        } else {      
          System.out.println("NOT OK: NOT CHECKED");    
        }
      }
    }
    
    //Turns the check flag on
    public void checkIt() {
      synchronized (synch) {
        check = true;
        synch.notify();
      }
    }

    //Wakes up this Runnable object causing exiting its run method
    public void stopIt() {
      synchronized (synch) {
        synch.notify();
      }
    }
  }
    

Listing 2. Using the Thread Pool Manager.

  import org.osgi.framework.BundleContext;
  import org.osgi.framework.BundleActivator;
  import org.osgi.framework.BundleException;
  import org.osgi.framework.ServiceReference;  
  import com.prosyst.util.threadpool.ThreadPoolManager;        

  public class TestActivator implements BundleActivator {

    ServiceReference tpoolManRef;
    ThreadPoolManager tpoolMan;  
    private static String servName = ThreadPoolManager.class.getName();

    public void start(BundleContext bc) throws BundleException {

      // Retrieving the Thread Pool Manager from the OSGi framework
      tpoolManRef = bc.getServiceReference(servName);  
      if(tpoolManRef != null) {
        tpoolMan = (ThreadPoolManager) bc.getService(tpoolManRef);  

        // Starting the execution of the RunnableTest job
        tpoolMan.execute(new RunnableTest(), "test");
      } else {
        throw new BundleException("No service reference is available!");
      }
    }  

    public void stop(BundleContext bc) {
      bc.ungetService(tpoolManRef);
    }
  }                  
      

Accessing Runnable Instances

If the thread that an entity operates in is taken from the pool of the ThreadPoolManager service, the entity can retrieve the associated Runnable job and make use of some additional functionality, offered by the job. Each thread in the thread pool is a com.prosyst.util.threadpool.ThreadContext instance whose getRunnable method returns the job presently attached to this thread.

Listing 3. Getting the current Runnable object from the thread pool.

                         . . .
    Thread current = Thread.currentThread();
    if (current instanceof ThreadContext) {
      Runnable runnable = ((ThreadContext) current).getRunnable();
    }
                         . . .
      

System Properties

The system properties, that can be set for the operation of the Database, are described in the Setup Guide.