-
Book Overview & Buying
-
Table Of Contents
-
Feedback & Rating

Java 9 Concurrency Cookbook, Second Edition
By :

In this recipe, we will learn how to do basic operations over a thread using the Java API. As with every element in the Java language, threads are objects. We have two ways of creating a thread in Java:
Thread
class and overriding the run()
method.Runnable
interface and the run()
method and then creating an object of the Thread
class by passing the Runnable
object as a parameter--this is the preferred approach and it gives you more flexibility.In this recipe, we will use the second approach to create threads. Then, we will learn how to change some attributes of the threads. The Thread
class saves some information attributes that can help us identify a thread, know its status, or control its priority. These attributes are:
Thread
objects. In Java 9, threads can have priority between 1 and 10, where 1 is the lowest priority and 10 is the highest. It's not recommended that you change the priority of the threads. It's only a hint to the underlying operating system and it doesn't guarantee anything, but it's a possibility that you can use if you want.Thread.State
enumeration: NEW
, RUNNABLE
, BLOCKED
, WAITING
, TIMED_WAITING
, or TERMINATED
. The following is a list specifying what each of these states means:NEW
: The thread has been created and it has not yet startedRUNNABLE
: The thread is being executed in the JVMBLOCKED
: The thread is blocked and it is waiting for a monitorWAITING
: The thread is waiting for another threadTIMED_WAITING
: The thread is waiting for another thread with a specified waiting timeTERMINATED
: The thread has finished its executionIn this recipe, we will implement an example that will create and run 10 threads that would calculate the prime numbers within the first 20,000 numbers.
The example for this recipe has been implemented using the Eclipse IDE. If you use Eclipse or a different IDE, such as NetBeans, open it and create a new Java project.
Follow these steps to implement the example:
Calculator
that implements the Runnable
interface:public class Calculator implements Runnable {
run()
method. This method will execute the instructions of the thread we are creating, so this method will calculate the prime numbers within the first 20000
numbers:@Override public void run() { long current = 1L; long max = 20000L; long numPrimes = 0L; System.out.printf("Thread '%s': START\n", Thread.currentThread().getName()); while (current <= max) { if (isPrime(current)) { numPrimes++; } current++; } System.out.printf("Thread '%s': END. Number of Primes: %d\n", Thread.currentThread().getName(), numPrimes); }
isPrime()
method. This method determines whether a number is a prime number or not:private boolean isPrime(long number) { if (number <= 2) { return true; } for (long i = 2; i < number; i++) { if ((number % i) == 0) { return false; } } return true; }
Main
that contains the main()
method:public class Main { public static void main(String[] args) {
System.out.printf("Minimum Priority: %s\n", Thread.MIN_PRIORITY); System.out.printf("Normal Priority: %s\n", Thread.NORM_PRIORITY); System.out.printf("Maximun Priority: %s\n", Thread.MAX_PRIORITY);
Thread
objects to execute 10 Calculator
tasks. Also, create two arrays to store the Thread
objects and their statuses. We will use this information later to check the finalization of the threads. Execute five threads (the even ones) with maximum priority and the other five with minimum priority:Thread threads[]; Thread.State status[]; threads = new Thread[10]; status = new Thread.State[10]; for (int i = 0; i < 10; i++) { threads[i] = new Thread(new Calculator()); if ((i % 2) == 0) { threads[i].setPriority(Thread.MAX_PRIORITY); } else { threads[i].setPriority(Thread.MIN_PRIORITY); } threads[i].setName("My Thread " + i); }
try (FileWriter file = new FileWriter(".\\data\\log.txt"); PrintWriter pw = new PrintWriter(file);) { for (int i = 0; i < 10; i++) { pw.println("Main : Status of Thread " + i + " : " + threads[i].getState()); status[i] = threads[i].getState(); } for (int i = 0; i < 10; i++) { threads[i].start(); }
join()
method to wait for this to happen. In this case, we want to write information about the threads when their statuses change, so we can't use this method. We use this block of code:boolean finish = false; while (!finish) { for (int i = 0; i < 10; i++) { if (threads[i].getState() != status[i]) { writeThreadInfo(pw, threads[i], status[i]); status[i] = threads[i].getState(); } } finish = true; for (int i = 0; i < 10; i++) { finish = finish && (threads[i].getState() == State.TERMINATED); } } } catch (IOException e) { e.printStackTrace(); } }
writeThreadInfo()
method to write information about the status of a thread in the file. This is the code for this method:private static void writeThreadInfo(PrintWriter pw, Thread thread, State state) { pw.printf("Main : Id %d - %s\n", thread.getId(), thread.getName()); pw.printf("Main : Priority: %d\n", thread.getPriority()); pw.printf("Main : Old State: %s\n", state); pw.printf("Main : New State: %s\n", thread.getState()); pw.printf("Main : ************************************\n"); }
The following screenshot shows the console part of the output of the program. We can see that all the threads we have created run in parallel to do their respective jobs:
In this screenshot, you can see how threads are created and how the ones with an even number are executed first, as they have the highest priority, and the others executed later, as they have minimum priority. The following screenshot shows part of the output of the log.txt
file where we write information about the status of the threads:
Every Java program has at least one execution thread. When you run the program, JVM runs the execution thread that calls the main()
method of the program.
When we call the start()
method of a Thread
object, we are creating another execution thread. Our program will have as many execution threads as the number of calls made to the start()
method.
The Thread
class has attributes to store all of the information of a thread. The OS scheduler uses the priority of threads to select the one that uses the CPU at each moment and actualizes the status of every thread according to its situation.
If you don't specify a name for a thread, JVM automatically assigns it one in this format: Thread-XX, where XX is a number. You can't modify the ID or status of a thread. The Thread
class doesn't implement the setId()
and setStatus()
methods as these methods introduce modifications in the code.
A Java program ends when all its threads finish (more specifically, when all its non-daemon threads finish). If the initial thread (the one that executes the main()
method) ends, the rest of the threads will continue with their execution until they finish. If one of the threads uses the System.exit()
instruction to end the execution of the program, all the threads will end their respective execution.
Creating an object of the Thread
class doesn't create a new execution thread. Also, calling the run()
method of a class that implements the Runnable
interface doesn't create a new execution thread. Only when you call the start()
method, a new execution thread is created.
As mentioned in the introduction of this recipe, there is another way of creating a new execution thread. You can implement a class that extends the Thread
class and overrides the run()
method of this class. Then, you can create an object of this class and call the start()
method to have a new execution thread.
You can use the static method currentThread()
of the Thread
class to access the thread object that is running the current object.
You have to take into account that the setPriority()
method can throw an IllegalArgumentException
exception if you try to establish priority that isn't between 1 and 10.
Change the font size
Change margin width
Change background colour