In simple concurrent applications, we execute concurrent tasks using the
Runnable interface and the
Thread class. We create and manage the threads and control their execution. We can't follow this approach in big concurrent applications because it can create many problems. For these cases, the Java concurrency API has introduced the Executor framework. In this chapter, we presented the basic characteristics and components that form this framework. First of all, we explored the
Executor interface, which defines the basic method to send a
Runnable task to an executor. This interface has a subinterface, the
ExecutorService interface, which includes methods to send to the executor tasks that return a result (these tasks implement the
Callable interface, as we will see in Chapter 5, Getting Data from Tasks - Callable and Future Interfaces), and a list of tasks.
ThreadPoolExecutor class is the basic implementation of both interfaces: adding additional methods to get information about...