我想了解线程池的逻辑,下面有一个简单的错误而不是完整的实现:
class ThreadPool {
private BlockingQueue<Runnable> taskQueue;
public ThreadPool(int numberOfThreads) {
taskQueue = new LinkedBlockingQueue<Runnable>(10);
for (int i = 0; i < numberOfThreads; i++) {
new PoolThread(taskQueue).start();
}
}
public void execute(Runnable task) throws InterruptedException {
taskQueue.put(task);
}
}
class PoolThread extends Thread {
private BlockingQueue<Runnable> taskQueue;
public PoolThread(BlockingQueue<Runnable> queue) {
taskQueue = queue;
}
public void run() {
while (true) {
try {
taskQueue.take().run();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
如果要执行的线程数超过taskQueue大小,调用线程是否会被阻塞怎么办?ThreadPoolExecutor - 这里我们可以看到,在这种情况下,这是一个被拒绝的执行处理程序的工作,但我仍然不能了解它是如何工作的。提前感谢您的帮助。
修改
将阻止队列的最大大小设置为10
答案 0 :(得分:5)
想象一组砌砖工(你的线)建造一堵墙和一堆砖(你的BlockingQueue)。
每个瓦工从堆中取出一块砖,定位它,然后选择另一块砖(taskQueue.take()) - 直到堆中有砖块,砖瓦工人一直忙着。
一辆卡车不时到达,堆满了更多的砖块 - 但堆上的空间有限,如果没有空间,卡车会停下来,等到砖瓦使用了足够的砖块。 / p>
只要堆中有足够的砖块(超过砌砖机的数量),您就可以放心所有砌砖工都有足够的工作 - 但当堆积开始时,砖砌工将不得不停止工作直到新砖块交付。
你必须选择合适数量的砖瓦,很少,卡车经常会在堆中等待空间,太多,而且大多数都会闲置等待新砖。
实现方面,一般来说,Java为您提供了一个线程池,您很少创建自己的 -
ExecutorService threadExecutor = Executors.newFixedThreadPool( 3 );
然后你打电话:
threadExecutor.submit(Runnable...);
将任务添加到队列中。
答案 1 :(得分:4)
如果要执行的线程数超过taskQueue大小,调用线程会被阻塞吗?
队列的大小是未运行的任务数。通常,即使线程繁忙,它也将为空。具有与线程数匹配的队列长度没有意义,此时没有什么特别的事情发生。
在这里我们可以看到,在这种情况下,它是被拒绝的执行处理程序
的工作
只有在队列已满时才会调用拒绝处理程序。您的队列没有限制,因此即使您支持此功能也不会调用它。
但是,如果确实有限制且支持此功能,则典型的行为是抛出异常。你可以让它做其他事情,比如阻止,让当前线程运行任务(这是我的偏好)或忽略任务。
我仍然无法理解它是如何运作的。
当您向队列提供()任务时,如果队列无法接受该任务,则返回false。发生这种情况时,请调用被拒绝的执行处理程序。