Follow these steps to implement the example:
- Create a class named Calculator that implements the Runnable interface:
public class Calculator implements Runnable {
- Implement the 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);
}
- Then, implement the auxiliar 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;
}
- Now implement the main class of the application. Create a class named Main that contains the main() method:
public class Main {
public static void main(String[] args) {
- First, write some information regarding the values of the maximum, minimum, and default priority of the threads:
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);
- Then create 10 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);
}
- We are going to write information in a text file, so create a try-with-resources statement to manage the file. Inside this block of code, write the status of the threads in the file before you launch them. Then, launch the threads:
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();
}
- After this, wait for the finalization of the threads. As we will learn in the Waiting for the finalization of a thread recipe of this chapter, we can use the 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();
}
}
- In the previous block of code, we called the 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");
}
- Run the program and see how the different threads work in parallel.