我有一定数量的线程。我希望每个线程一个接一个地运行三个Runnable
。这是一些伪代码来解释:
Thread[] threads = new Thread[4];
for (int i = 0; i < threads.length; i++) {
// Set the first tasks.
threads[i] = new Thread(new FirstRunnable());
threads[i].start();
}
for (int i = 0; i < threads.length; i++)
threads[i].join(); // wait until the first tasks are done
for (int i = 0; i < threads.length; i++) {
// Set the second task.
threads[i].setRunnable(new SecondRunnable());
threads[i].start();
}
for (int i = 0; i < threads.length; i++)
threads[i].join(); // wait until the second tasks are done
...
使用ThreadPool
听起来有点过分,特别是因为我的性能,性能和性能都在提高。在Java中实现它的最佳方法是什么?
答案 0 :(得分:4)
每当您看到new Thread(...).start()
时,请使用Executors
框架。特别是,请使用Executors.newFixedThreadPool(...)
。
答案 1 :(得分:1)
您可以使用CyclicBarrier和“CombinedRunnable”,如下所示。屏障允许所有线程在完成下一次运行之前等待彼此完成。
CyclicBarrier barrier = new CyclicBarrier(4);
Runnable r = new CombinedRunnable(barrier, new FirstRunnable(), new SecondRunnable());
Thread[] threads = new Thread[4];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(r);
threads[i].start();
}
CombinedRunnable类:
public class CombinedRunnable implements Runnable{
private final CyclicBarrier barrier;
private final Runnable[] runnables;
public CombinedRunnable(CyclicBarrier barrier, Runnable... runnables){
this.barrier = barrier;
this.runnables = runnables;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
for(Runnable r: runnables){
r.run();
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
答案 2 :(得分:1)
似乎很适合Executors类的newFixedThreadPool。
所以你的代码看起来像:
ExecutorService es = Executors.newFixedThreadPool(4);
List<Future> futures = new ArrayList<Future>();
for (int x = 0; x < 4; x ++) {
futures.add(es.submit(new FirstRunnable()));
}
while (futures.size() > 0) {
futures.remove(0).get();
}
for (int x = 0; x < 4; x ++) {
futures.add(es.submit(new SecondRunnable()));
}
while (futures.size() > 0) {
futures.remove(0).get();
}
当然,您可以轻松地重构上面的代码以删除代码重复。
答案 3 :(得分:0)
实现此目的的惯用方法是将Executor
与CompletionService
结合使用。这允许您将许多工作单元映射到固定大小的线程池,并提供一种优雅的阻塞机制,直到所有工作完成。
请注意,您对使用线程池的方式可能会影响效率的问题并不是真正的问题:主要的开销是创建单个线程,无论如何都是这样做的;创建池的额外对象创建开销可以忽略不计。
// Create fixed thread pool and wrap in a CompletionService to allow for easy access to completed tasks.
// We don't have an explicit result for each Runnable so parameterise the service on Void.
CompletionService<Void> cs = new ExecutorCompletionService<Void>(Executors.newFixedThreadPool(3));
// Create units of work for submission to completion service.
Runnable[] runnables = ...
// Submit runnables. Note that we don't care about the result so pass in null.
for (Runnable r : runnables) {
cs.submit(r, null);
}
// Take each *completed* result in turn, blocking until a completed result becomes available.
for (int i=0; i<runnables.length; ++i) {
Future<Void> completed = cs.take();
}
答案 4 :(得分:-2)
Executor Framework适合您。
这是伪代码:
1.创建执行者服务
Executors type1Runnables = Executors.newFixedThreadPool(4);
Executors type2Runnables = Executors.newFixedThreadPool(4);
等。
2.向其提交任务
for(){
type1Runnables.submit(new Runnable1());
type2Runnables.submit(new Runnable2);
}
3。调用执行程序
type1Runnables.invokeAll();
type2Runnables.invokeAll();
为了使它更通用,您可以编写自己的executorservicefactory,它接受不同的runnable类型。