对于每个正在运行的任务,我确实需要一个单独的线程,因此更改架构不是一种选择。
如果是这样(例如,调用外部阻塞函数),则为它们创建单独的线程并启动它们。您不能创建具有有限数量线程的线程池,因为其中一个线程中的阻塞函数将阻止将任何其他可运行对象放入其中,并且创建每个任务一个线程的线程池并不会获得太多收益。
我尝试使我的 threadPool 大小等于 Runtime.getRuntime().availableProcessors() ,它试图运行所有 500 个线程,但只让它们中的 8 个(4xhyperthreading)执行。
当您将创建的 Thread 对象传递给线程池时,它只会看到它们实现了Runnable
. 因此,它将运行每个Runnable
完成。任何停止方法返回的循环run()
都不允许下一个入队任务运行;例如:
public static void main (String...args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i = 0; i < 10; ++i) {
final int task = i;
executor.execute(new Runnable () {
private long lastRunTime = 0;
@Override
public void run () {
for (int iteration = 0; iteration < 4; )
{
if (System.currentTimeMillis() - this.lastRunTime > TIME_OUT)
{
// do your work here
++iteration;
System.out.printf("Task {%d} iteration {%d} thread {%s}.\n", task, iteration, Thread.currentThread());
this.lastRunTime = System.currentTimeMillis();
}
else
{
Thread.yield(); // otherwise, let other threads run
}
}
}
});
}
executor.shutdown();
}
打印出来:
Task {0} iteration {1} thread {Thread[pool-1-thread-1,5,main]}.
Task {1} iteration {1} thread {Thread[pool-1-thread-2,5,main]}.
Task {0} iteration {2} thread {Thread[pool-1-thread-1,5,main]}.
Task {1} iteration {2} thread {Thread[pool-1-thread-2,5,main]}.
Task {0} iteration {3} thread {Thread[pool-1-thread-1,5,main]}.
Task {1} iteration {3} thread {Thread[pool-1-thread-2,5,main]}.
Task {0} iteration {4} thread {Thread[pool-1-thread-1,5,main]}.
Task {2} iteration {1} thread {Thread[pool-1-thread-1,5,main]}.
Task {1} iteration {4} thread {Thread[pool-1-thread-2,5,main]}.
Task {3} iteration {1} thread {Thread[pool-1-thread-2,5,main]}.
Task {2} iteration {2} thread {Thread[pool-1-thread-1,5,main]}.
Task {3} iteration {2} thread {Thread[pool-1-thread-2,5,main]}.
Task {2} iteration {3} thread {Thread[pool-1-thread-1,5,main]}.
Task {3} iteration {3} thread {Thread[pool-1-thread-2,5,main]}.
Task {2} iteration {4} thread {Thread[pool-1-thread-1,5,main]}.
...
显示第一个(线程池大小)任务在安排下一个任务之前运行完成。
您需要做的是创建运行一段时间的任务,然后让其他任务运行。您如何构建这些取决于您想要实现的目标
- 是否希望所有任务同时运行,都等待一分钟,然后再次同时运行,或者任务是否彼此不同步
- 您是否真的希望每个任务以一分钟的间隔运行
- 您的任务是否可能阻塞,因此确实需要单独的线程
- 如果任务阻塞的时间长于预期的运行窗口,预期会有什么行为
- 如果任务阻塞时间超过重复率(阻塞超过一分钟),预期会有什么行为
根据对这些问题的回答,可以使用 ScheduledExecutorService、信号量或互斥锁的某种组合来协调任务。最简单的情况是非阻塞、非同步任务,在这种情况下,直接使用 ScheduledExecutorService 每分钟运行一次您的可运行文件。