What is an ExecutorService?

To be honest, this question is not too new. More than 13 years have passed since the release of Java 5 and the java.util.concurrent. * Package, but in all my ten years of practice, I have never had to face this beast. Nevertheless, I was asked this question several times during interviews and had to get acquainted.



Naturally, the first thing I started with is Habr. But, unfortunately, I found only two articles here:



habrahabr.ru/post/260953

habrahabr.ru/post/116363



The first, obviously, for those who understand and have experience with ExecutorService. The second, unfortunately, did not enter me. It seems small and "on the case", but after rereading several times I still do not understand what ExecutorService is and what it is eaten with. So I had to sit down at Eclipse, smoke, read javadoc and figure it out.



So let's take a look at a simple example:



ExecutorService service = Executors.newFixedThreadPool(3);
service.execute(new Runnable() {
    public void run() {
        System.out.println("Another thread was executed");
    }
});

      
      





In this example, we created the ExecutorService object itself and called the execute method on it. Passing the most common thread implementation to it. All this could have been built in the old grandfather's way, but this, you see, is much simpler and more elegant. In fact, we quickly branched off another, asynchronous thread from the current thread, which can do something there in the background.

We created the ExecutorService object using a factory. Its methods are quite obvious, so we won't be too busy. Here is some of them:



ExecutorService service1 = Executors.newSingleThreadExecutor();
ExecutorService service2 = Executors.newFixedThreadPool(3);
ExecutorService service3 = Executors.newScheduledThreadPool(3);

      
      





In addition to the execute method, which is called on the "fire and forget" principle, our service also has a submit method. The only difference from the former is that the latter returns an object of the Future interface. This is just a great opportunity to control the state of the thread that we have started in the background. It is done something like this:



Future future = service.submit(new Runnable() {
    public void run() {
        System.out.println("Another thread was executed");
    }
});
...
future.get();

      
      





Note that the get method will deadly block the current thread and will wait until the background thread finishes. Now you don't need all these unobvious joins! If we are afraid that our background thread will never finish, we can use get (long, TimeUnit).



Sometimes you have to return data from a background thread to the current one. The submit method will also help us with this, but now we need to pass to it not a Runnable, but a Callable object. In fact, these are two identical interfaces, the only difference is that the latter can return something:



Future future = service.submit(new Callable(){
    public Object call() throws Exception {
        System.out.println("Another thread was executed");
        return "result";
    }
});
...
System.out.println("Result: " + future.get());

      
      





Well, in short, that's all. Were methods of creating ExecutorService-and in the factory (which there are many), were the methods of the ExecutorService, error handling issues in a background thread, but that's another story ...



At the end of do not forget to:



servcie.shutdown();

      
      





Or not, if all background threads are daemons.



All Articles