ExecutorService SingleThreadExecutor

时间:2016-03-31 08:49:47

标签: java multithreading executorservice

我有一个对象列表,根据用户交互,某些对象需要异步工作。像这样:

for(TheObject o : this.listOfObjects) {
   o.doWork();
}

TheObject实现了ExecutorService(SingleThread!),用于完成工作。 TheObject类型的每个对象都实例化ExecutorService。我不想做lasagna code。我没有同时拥有足够的对象,以创建一个需要线程池的额外提取层。

我想引用有关CachedThreadPools

的Java文档
  

未使用60秒的线程终止并且   从缓存中删除。因此,一个闲置足够长时间的池   不会消耗任何资源。

第一个问题: SingleThreadExecutor也是如此吗?线程是否被终止? JavaDoc并没有提及任何有关SingleThreadExecutor的内容。在这个应用程序中它甚至不重要,因为我有一些可以依靠的对象。只是好奇心。

此外,doWork() TheObject方法需要调用ExecutorService#.submit()方法来执行异步工作。是否有可能(我敢打赌)隐含地调用doWork()方法?这是设计异步方法的可行方法吗?

void doWork() {
   if(!isRunningAsync) {
      myExecutor.submit(doWork());
   } else {
      // Do Work...
   }
}

2 个答案:

答案 0 :(得分:7)

  

第一个问题:SingleThreadExecutor也是如此吗?线程是否被终止?

查看Executors的源代码,比较newCachedThreadPoolnewSingleThreadExecutor的实现:

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

主要区别(此处感兴趣)是60L, TimeUnit.SECONDS0L, TimeUnit.MILLISECONDS

有效地(but not actually),这些参数将传递给ThreadPoolExecutor.setKeepAliveTime。看一下该方法的Javadoc:

  

时间值为零将导致多余的线程在执行任务后立即终止。

其中“多余线程”实际上是指“超过核心池大小的线程”。

  • 使用零核心线程和(有效)无限数量的非核心线程创建缓存线程池;因此,任何线程都可以在保持活动时间之后终止。
  • 使用1个核心线程和零个非核心线程创建单线程执行程序;因此,在保持活动时间之后没有可以终止的线程:它的一个核心线程保持活动状态,直到你关闭整个ThreadPoolExecutor

(感谢@GPI指出我之前的解释错误。)

答案 1 :(得分:2)

第一个问题:

  

终止未使用60秒的线程并从缓存中删除。因此,长时间闲置的池不会占用任何资源。

     

对于SingleThreadExecutor也是如此吗?

SingleThreadExecutor的工作方式不同。由于创建期间配置的值,它没有超时概念。

终止SingleThread是可能的。但它保证始终存在一个Thread来处理来自任务队列的任务。

来自newSingleThreadExecutor文档:

public static ExecutorService newSingleThreadExecutor()
  

创建一个Executor,它使用一个在无界队列中运行的工作线程。 (但请注意,如果此单个线程由于在关闭之前执行期间的故障而终止,则在需要执行后续任务时将使用新的线程。)

保证任务按顺序执行,并且在任何给定时间不会有多个任务处于活动状态。与其他等效的newFixedThreadPool(1)不同,保证返回的执行程序不可重新配置以使用其他线程。

第二个问题:

  

此外,TheObject的doWork()方法需要调用ExecutorService#.submit()方法来执行异步工作

for(TheObject o : this.listOfObjects) {
   o.doWork();
}

可以更改为

ExecutorService executorService = Executors.newSingleThreadExecutor();

executorService.execute(new Runnable() {
    public void run() {
        System.out.println("Asynchronous task");
    }
});

executorService.shutdown();

使用CallableRunnable界面,并使用doWork方法或run()方法添加call()()代码。任务将同时执行。