【问题标题】:Exactly what a Thread Pool in Java doing?Java中的线程池到底在做什么?
【发布时间】:2012-05-08 19:29:35
【问题描述】:
与任何 ExecutorServices 一样,我们定义了一个大小为 3 的 newFixedPool。现在我有一个大约 10000 个可运行任务的队列。
对于执行上述过程,我有这些疑问 -
要执行上面的流程,executor会不会让任务队列中的3个线程一次性运行?
Pool 将承载 3 个线程,而这 3 个线程将只负责执行所有 10000 个任务。如果它是正确的,单个线程如何运行不同的可运行任务,因为最终这些任务也是线程本身,并且在任何作业/任务运行的中间,您可以将新的职责分配给池线程。
【问题讨论】:
标签:
java
multithreading
threadpool
【解决方案1】:
下面是 java 中的 customThreadPool,它接受 noofThreads 和 MaxConcurrentTask。
它还有 stop() 来停止完整的线程池
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
@SuppressWarnings("all")
public class ThreadPool {
private BlockingQueue taskQueue = null;
private List<PoolThread> threads = new ArrayList<PoolThread>();
private boolean isStopped = false;
public ThreadPool(int noOfThreads, int maxNoOfTasks) {
taskQueue = new LinkedBlockingQueue(maxNoOfTasks);
for(int i=0; i<noOfThreads; i++) {
threads.add(new PoolThread(taskQueue));
}
for(PoolThread thread : threads) {
thread.start();
}
}
public synchronized void execute(Runnable task) {
if(this.isStopped)
throw new IllegalStateException("ThreadPool is stopped");
this.taskQueue.offer(task);
}
public synchronized void stop() {
this.isStopped = true;
for(PoolThread thread : threads) {
thread.stopMe();
}
}
}
@SuppressWarnings("all")
class PoolThread extends Thread {
private BlockingQueue taskQueue = null;
private boolean isStopped = false;
public PoolThread(BlockingQueue queue) {
taskQueue = queue;
}
public void run() {
while(!isStopped()) {
try {
Runnable runnable = (Runnable) taskQueue.poll();
runnable.run();
} catch(Exception e) {
//log or otherwise report exception, //but keep pool thread alive.
}
}
}
public synchronized void stopMe() {
isStopped = true;
this.interrupt();
//break pool thread out of dequeue() call.
}
public synchronized boolean isStopped() {
return isStopped;
}
}
【解决方案2】:
是的,如果实际上您使用的是Executors.newFixedThreadPool(3)
,那么池中一次最多只有 3 个线程
10,000 个任务不是Threads,它们只是Runnables。 Thread 必须通过 Thread#start 启动才能实际创建系统线程。任务(Runnable 的实例)放置在 BlockingQueue 中。线程池中的线程将轮询 BlockingQueue 以获取要运行的任务。当他们完成任务时,他们会返回队列去获取另一个任务。如果添加了更多任务,则根据该队列的执行规则将它们插入BlockingQueue。对于大多数队列来说,这是先进先出,但 PriorityQueue 实际上使用 Comparator 或自然顺序在插入任务时对其进行排序。