Thread scheduling
When a Java thread is created, the thread inherits its priority from the parent thread. The priority of the thread varies from
MIN_PRIORITY to
MAX_PRIORITY, where the default priority is
NORM_PRIORITY. After a thread is created, the
setPriority method can be used to alter the priority of the thread.
A selfish thread is a thread that executes in a tight loop without giving up control either by explicitly yielding or by initiating a blocking operation.
Since the thread-scheduling algorithm on Nonstop is nonpreemptive and does not time slice, it is possible for such a thread to prevent other threads from getting access to CPU time. Theoretically, such a thread can run forever. However, after a while, the operating system periodically reduces the priority of the process in stages, until its priority reaches to a lower value.
For a demonstration of scheduling on a NonStop system, review the results and output of the following programs:
Snnipet for ThreadTimeSlice feature
import java.io.*;
import java.lang.*;
class LoopThread extends Thread {
private Thread t;
private int threadNum;
private static int tick = 1;
private static volatile int numThreadsStillRunning = 0;
private static int maxThreads = -1;
private static volatile int numThreadsCreated = 0;
public static void setMaxThreads(int num) { maxThreads = num; }
LoopThread( int num){
if ( num <= 0 || num > maxThreads ) {
System.out.println("Invalid thread number: " + num);
System.exit(1);
}
threadNum = num;
System.out.println("Creating " + threadNum );
numThreadsCreated++;
numThreadsStillRunning++;
}
public void run() {
if ( threadNum == 1 ) {
// First thread. Execute until other threads terminates
while ( numThreadsCreated < maxThreads ||
numThreadsStillRunning > 1 ) {
tick++;
}
} else {
// Sleep some time to guarantee first thread runs
try {
Thread.sleep(10);
} catch ( InterruptedException e ) {
System.out.println("Sleep interrupted.");
}
for (int i=0; i < 10000; i++ ) {
tick++;
}
}
System.out.println("Thread " + threadNum + " exiting.");
numThreadsStillRunning--;
}
}
public class ThreadPreemptionDemo {
public static void main(String args[])
{
int numThreadsToCreate = 2;
// LoopThread[] threads;
if ( args.length > 0 ) {
// User has specified number of threads to create
numThreadsToCreate = Integer.parseInt(args[0]);
if ( numThreadsToCreate < 2 ) {
System.out.println("Invalid argument. Minimum value = 2");
System.exit(1);
}
}
LoopThread[] threads = new LoopThread[numThreadsToCreate];
LoopThread.setMaxThreads(numThreadsToCreate);
for (int i = 0; i < numThreadsToCreate; i++) {
threads[i] = new LoopThread(i+1);
threads[i].start();
}
try {
for (int i = 0; i < numThreadsToCreate; i++) {
threads[i].join();
}
} catch (InterruptedException ex) {
System.out.println("Exception " + ex);
}
}
}
On the NonStop system, the execution of threads are not time sliced. When a thread gets a chance to run, it enters the loop and starves the other thread. Hence, the application hangs.
java -cp . ThreadPreemptionDemo
Creating 1
Creating 2
You will observe a hang when thread time slice option or time slice policy option is not specified. Therefore, “Creating 2” in the output may or may not be printed.
The Java runtime supports a simple, deterministic, scheduling algorithm known as fixed-priority scheduling. The Java runtime does not time-slice. For the NonStop system, the thread-scheduling algorithm is not preemptive; that is, a thread continues to run until it explicitly yields or otherwise causes a yield by initiating a blocking operation on the thread. When a thread gives up control, the runnable threads of the highest priority are run in first-in-first-out order. A lower priority thread is run (also in first-in-first-out order) only when no runnable threads of a higher priority are available.
Thread time slice
NSJ includes a JVM-forced, preemptive thread scheduling feature. This feature also provides an option to specify the time slice for threads. A thread will run for the specified time slice, after which another thread gets dispatched from the ready queue. This helps in force-yielding a thread which consumes large processor time so that the other ready threads also get the processor time to run.
To enable pre-emptive user threads, use the following option:
-XX:ThreadTimeSlice[=T]
Where,
T is an optional argument.
The default value is calculated by dividing 400 ms by the number of cores on the CPU. For example, if a CPU has four cores, the default time slice value is 400 ms / 4 which is 100 ms.
- The value of T can range between 1 to 32767.
If the specified value of T is above 32767, the value is time-sliced to 32767.
If the specified value of T is 0, the default value is used for time slice.
Following is the output for the snippet provided in Example:
java -cp . -XX:ThreadTimeSlice=10 ThreadPreemptionDemo
Creating 1
Creating 2
Thread 2 exiting
Thread 1 exiting

