Downside of the Executor Service with context to thread local

Downside of the Executor Service with context to thread local

The executor service creates a pool of threads that you can submit tasks to. The benefit of this approach is that you don’t have to manage the reusing of threads yourself, but Java will do this for you. This way, the threads are only created once and will be reused if the executor service is in scope.

There are also some downsides with the ExecutorService.

The first downside is that when a thread is blocked, it won’t pick up a next task to run in the meantime. Threads rather block and wait than picking up a new task. This is problematic because we can only have a limited number of threads. These threads take up a relatively small amount of memory, but there is still a hard limit based on the amount of memory available. If you have a lot of small tasks, the changes are that you will be out of memory way before your CPU is fully utilized

The next problem with ExecutorService is that threads are reused. You are probably wondering right now how this can be a good and a bad thing. Reusing threads is good, but there are little bugs that can sneak into your code when you are not careful with reusing threads. One of these problematic use cases is when tasks use thread local variables. When a task sets a thread local variable but forgets to unset it, the thread the task just ran on will be placed back into the pool with that thread local variable. The next task running on this thread will be able to read the thread local variable from the previous task. This is bad because then your thread local variables are leaking into other threads which can cause all kinds of trouble

 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;

 public class Main {
     public static ThreadLocal < String > threadLocal = new
     ThreadLocal < > ();
     public static void main(String[] args) {
         try (ExecutorService executor = Executors.newFixedThreadPool(1)) {
             executor.submit(() - > {
                 threadLocal.set("Task 1 value");
                 System.out.println("Task 1: " +
                     threadLocal.get());
             });
             executor.submit(() - > {
                 String value = threadLocal.get();
                 System.out.println("Task 2: " + value);
             });
         }
     }
 }        

The output of the code example is as follows:

Task 1: Task 1 value

Task 2: Task 1 value

we created two tasks and an executor service that uses a single thread to run these tasks. The first task sets a thread local variable but does not unset it. So, when task two runs on that same thread, it can access the thread local variable from task one which ran first on that thread. You can see this happening in the output where the value for tasks one and two is the same.

要查看或添加评论,请登录

?? Saral Saxena ???????的更多文章

社区洞察

其他会员也浏览了