2012-09-17 51 views
2

是否有ExecutorService允许现有线程执行执行而不是产生新线程?如果它是ScheduledExecutor,则为奖励。大多数执行程序产生工作线程来执行执行,但我希望工作线程成为我所在的现有线程。下面是我想象中的API:阻塞线程上是否存在ExecutorService?

while (!executor.isTerminated()) { 
    Runnable r = executor.take(); 
    r.run(); 
} 

这是类似的方式,SWT和JavaFX允许主线程分派事件,而不是摇摆,这就需要其自身的事件分派线程来催生来处理事件。

动机:我目前有很多地方在线程产生一个新的执行程序,然后调用awaitTermination()等待它完成。我想节省一些资源并保持堆栈轨迹不被分成两部分。

请注意,我不希望在execute(Runnable)的调用者线程中执行任务的执行程序,这是this answer和Guava的MoreExecutors.sameThreadExecutor()所做的。

+0

请问['Executors.newSingleThreadExecutor()'](http://docs.oracle.com/javase/7/docs /api/java/util/concurrent/Executors.html#newSingleThreadExecutor%28%29)?或者['Executors.newScheduledThreadPool(1)'](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newScheduledThreadPool%28int%29)? – assylias

+1

'take()'表示在你看到它的返回值为真后,假设的'Executor#isTerminated()'谓词的答案是否变为false? – seh

+0

@seh据推测,'isTerminated'会读取一些'volatile'变量,这个变量可以被另一个线程改变,要求它终止。这是一个关于并发性的问题,毕竟:3 – Brian

回答

0

我假设你想要的是在创造新的线程,如姓名,守护状态等控制使用ThreadFactory

public class MyThreadFactory implements ThreadFactory { 
    public Thread newThread(Runnable runnable) { 
     Thread t = new Thread(runnable, "MyThreadName"); 
     t.setDaemon(true); 
     return t; 
    } 
} 

这使您可以控制线程的创建,使执行发生在线程制造,而不是从默认ThreadFactory一些默认线程。

然后使用它,所有的Executors方法采取ThreadFactory

Executors.newExecutorOfSomeKind(new MyThreadFactory()); 

编辑:我明白你的意思了。不幸的是,所有Executor实现(据我所知)的行为是创建新线程来运行任务,除了你提到的sameThreadExecutor。没有通过Thread创建执行程序的对象来执行一项任务(这是一个糟糕的设计 - 请参阅我的意思),但没有简单的方法来完成您想要的任务。我建议将代码更改为使用单个Executor,例如ExecutorCompletionService(请参阅this question)或使用分支/连接模式。在Java 7中,fork/join更加容易(请参阅this Java trail)。对于Java 7之前的代码,请阅读Java中的计数Semaphore(和in general)。

+0

反对“可怕的设计”。java.util.concurrent中没有任何一个Executor实现创建新线程对于每个任务 –

+0

@Alexei Kaigorodov请参阅缓存线程池 - http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool%28%29。If你有很多长时间运行的任务,每个任务都有自己的线程 –

+0

@John Vint可能性,但不是一个规则,如果它可以重用现有的线程,也就是说,它们的线程的run()方法会包含TS建议的循环任务队列。 –

3

来自java.util.concurrent的大多数执行者的行为与您的假设完全相同。有些任务过多时会产生额外的线程,但通常可以将其配置为设置限制。

要利用这种行为,请不要每次启动新的执行程序 - 使用相同的执行程序。要等待一组任务完成,请使用invokeAll()submit(),然后使用future.get()