我有两个名为j1和j2的连续作业。这两个工作没有任何共享状态。 我想编写一个接收未知大小的线程池并在两个作业上共享它的程序,如果线程池大小为1,则唯一的线程用于这两个作业。在以下代码中,j2永远不会启动。 我只想要一个替代方案,以便在两个作业之间共享单个线程(例如循环法)
@Test
public void testConcurrency(){
final Runnable j1 = new Runnable() {
@Override
public void run() {
while (!Thread.interrupted()) {
System.out.println("a");
}
}
};
final Runnable j2 = new Runnable() {
@Override
public void run() {
while (!Thread.interrupted()) {
System.out.println("b");
}
}
};
final ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(j1);
executorService.submit(j2);
executorService.shutdown();
}
我正在尝试开发一个体系结构,以便在所有模块中使用特定数量的线程池来完成不同的任务。这样我就可以控制创建的线程数,我只需要将它们注入模块中。而且我不想因为像这样的代码而面临死锁。所以我想知道是否有像我提到的代码块的替代品。 我曾考虑强迫开发人员使用ScheduledExecutor而不是无限循环,我只是想知道是否有遗漏的东西我已经看不到了。
答案 0 :(得分:2)
您必须自己在任务之间切换。例如,您可以通过以下方式定义抽象任务:
public abstract class AbstractContinuousTask implements Runnable {
private long maxDurationInMs = 100;
private ExecutorService execService;
public AbstractContinousTask(long maxDurationInMs, ExecutorService execService) {
this.maxDurationInMs = maxDurationInMs;
this.execService = execService;
}
@Override
public final void run() {
long start = System.currentTimeMillis();
while (!Thread.interrupted() && (System.currentTimeMillis() - start < maxDurationInMs)) {
runInternal();
}
execService.submit(this);
}
public abstract void runInternal();
}
将在给定的持续时间内调用runInternal方法(您可以在返回之前设置一些调用等等)。
然后,您的任务定义变为:
final ExecutorService executorService = Executors.newSingleThreadExecutor();
final Runnable j1 = new AbstractContinousTask(100, executorService) {
@Override
public void runInternal() {
System.out.println("a");
}
};
final Runnable j2 = new AbstractContinousTask(100, executorService) {
@Override
public void runInternal() {
System.out.println("b");
}
};
编辑: 我刚刚看到你关于开发调度架构的最后评论。您是否查看过调度库,如Quartz或Spring(使用@Scheduled注释)?
你也可以直接使用java Timer api,这样:
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("a");
}
}, 0, 100);
t.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("b");
}
}, 0, 100);