Perform the following steps to implement the example:
- First, implement your own worker thread class. Create a class named AlwaysThrowsExceptionWorkerThread that extends the ForkJoinWorkerThread class:
public class AlwaysThrowsExceptionWorkerThread extends
ForkJoinWorkerThread {
- Implement the constructor of the class. It receives a ForkJoinPool class as a parameter and calls the constructor of its parent class:
protected AlwaysThrowsExceptionWorkerThread(ForkJoinPool pool) {
super(pool);
}
- Implement the onStart() method. This is a method of the ForkJoinWorkerThread class and is executed when the worker thread begins its execution. The implementation will throw a RuntimeException exception upon being called:
protected void onStart() {
super.onStart();
throw new RuntimeException("Exception from worker thread");
}
- Now, implement the factory needed to create your worker threads. Create a class named AlwaysThrowsExceptionWorkerThreadFactory that implements the ForkJoinWorkerThreadFactory interface:
public class AlwaysThrowsExceptionWorkerThreadFactory implements
ForkJoinWorkerThreadFactory {
- Implement the newThread() method. It receives a ForkJoinPool object as the parameter and returns a ForkJoinWorkerThread object. Create an AlwaysThrowsExceptionWorkerThread object and return it:
@Override
public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
return new AlwaysThrowsExceptionWorkerThread(pool);
}
- Implement a class that will manage the exceptions thrown by worker threads. Implement a class named Handler that implements the UncaughtExceptionHandler interface:
public class Handler implements UncaughtExceptionHandler {
- Implement the uncaughtException() method. It receives as parameters a Thread object and a Throwable object and is called by the ForkJoinPool class each time a worker thread throws an exception. Write a message to the console and exit the program:
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.printf("Handler: Thread %s has thrown an
Exception. ",t.getName());
System.out.printf("%s ",e);
System.exit(-1);
}
- Now, implement a task to be executed in the ForkJoinPool executor. Create a class named OneSecondLongTask that extends the RecursiveAction class:
public class OneSecondLongTask extends RecursiveAction{
- Implement the compute() method. It simply puts the thread to sleep after one second:
@Override
protected void compute() {
System.out.printf("Task: Starting. ");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("Task: Finish. ");
}
- Now, implement the main class of the example. Create a class named Main with a main() method:
public class Main {
public static void main(String[] args) {
- Create a new OneSecondLongTask object:
OneSecondLongTask task=new OneSecondLongTask();
- Create a new Handler object:
Handler handler = new Handler();
- Create a new AlwaysThrowsExceptionWorkerThreadFactory object:
AlwaysThrowsExceptionWorkerThreadFactory factory=new
AlwaysThrowsExceptionWorkerThreadFactory();
- Create a new ForkJoinPool object. Pass as parameters the value 2, the factory object, the handler object, and the value false:
ForkJoinPool pool=new ForkJoinPool(2,factory,handler,false);
- Execute the task in the pool using the execute() method:
pool.execute(task);
- Shut down the pool with the shutdown() method.
pool.shutdown();
- Wait for the finalization of the tasks using the awaitTermination() method:
try {
pool.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
- Write a message indicating the end of the program:
System.out.printf("Task: Finish. ");