我被要求在面试中创建自己的线程池,我必须创建用户请求的线程数。允许用户提交任务并最终关闭池。我编写了下面的程序,除了关闭以外的所有情况都能正常工作。
public class ThreadPool
{
public final Queue<Runnable> workerQueue;
private static boolean isrunning = true;
private Thread[] workerThreads;
public ThreadPool(int N)
{
workerQueue = new LinkedList<>();
workerThreads = new Thread[N];
for (int i = 0; i < N; i++) {
workerThreads[i] = new Worker("Pool Thread " + i);
workerThreads[i].start();
}
}
public void shutdown()
{
while(isrunning){
if(workerQueue.isEmpty()){
isrunning = false;
}
}
}
public void submit(Runnable r) throws Exception
{
workerQueue.add(r);
}
private class Worker extends Thread
{
public Worker(String name)
{
super(name);
}
public void run()
{
while (isrunning) {
try {
if(!workerQueue.isEmpty())
{
Runnable r = workerQueue.poll();
r.run();
}
} catch (RuntimeException e) {
e.printStackTrace();
}
}
}
}
}
我写的测试方法如下
static public void main(String[] args) throws Exception
{
ClassA a1 = new ClassA();
ClassA a2 = new ClassA();
ClassA a3 = new ClassA();
ClassA a4 = new ClassA();
ClassA a5 = new ClassA();
ClassA a6 = new ClassA();
ThreadPool tp = new ThreadPool(5);
tp.submit(a1);
tp.submit(a2);
tp.submit(a3);
tp.submit(a4);
tp.submit(a5);
///////////////
tp.submit(a6);
tp.shutdown();
}
但程序永远不会结束,它总是在运行,我必须在eclipse中手动停止它。但是如果我在方法关闭时添加一个简单的System.out.print(&#34;&#34;),它就会正常工作(程序在所有线程执行后结束)。
你能告诉我为什么它与sysout一起工作以及它为什么不使用它?
答案 0 :(得分:0)
您的代码存在两个主要问题:
您正在使用在多线程环境中未同步的Queue
实现。当多个线程从队列中插入/删除时,这会导致Race Condition。请考虑使用以下内容:
workerQueue = new ConcurrentLinkedQueue()
你运行了一些非常紧凑的循环,一个是Worker.run()
方法中的一个,你不会检查NPE而不允许某些&#34;冷却&#34;和另一个循环shutdown()
:
while (isrunning) {
...
Runnable r = workerQueue.poll();
r.run();
...
}
这与1一起导致Queue
被清空而没有正确更新尺寸信息:即。 isEmpty()
返回false
但poll()
返回null。你的程序将陷入循环。由于特定于您的配置的不同时序而添加System.out.print()
时,这种情况不会发生(在其他环境中可能会继续失败 - 特别是在可用的cpu核心数超过6的情况下)。