Java 正在中断线程池中的BlockingQueue take()

Java 正在中断线程池中的BlockingQueue take(),java,multithreading,threadpool,blockingqueue,Java,Multithreading,Threadpool,Blockingqueue,我有一个线程池,它创建工人,工人从阻塞队列获取作业。 线程等待队列中的take()。 即使显式调用运行线程的线程中断方法,它们仍然在等待take()。处理阻塞队列的正确方法是什么 public class ThreadPoolGen { static final Logger LOG = Logger.getLogger(ThreadPoolGen.class); private LinkedBlockingQueue<Runnable> queue; pr

我有一个线程池,它创建工人,工人从
阻塞队列
获取作业。 线程等待队列中的
take()
。 即使显式调用运行线程的线程中断方法,它们仍然在等待
take()
。处理阻塞队列的正确方法是什么

public class ThreadPoolGen {
    static final Logger LOG = Logger.getLogger(ThreadPoolGen.class);

    private LinkedBlockingQueue<Runnable> queue;
    private int threadCount;
    private Worker[] workers;
    private Thread[] workerThreads;

    public ThreadPoolGen(int count) throws CountException{

        if(isValidCount(count))
            this.threadCount = count;
        else
            throw new CountException("Invalid Thread Count");

        workers = new Worker[count];
        workerThreads = new Thread[count];
        queue = new LinkedBlockingQueue<Runnable>();
        startThreads();
    }

    public boolean execute(Runnable task){
        return queue.offer(task);
    }

    private void startThreads(){
        synchronized (this) {

            for(int i=0;i<threadCount;i++){

                workers[i] = new Worker();
                workerThreads[i] = new Thread(workers[i]);
                workerThreads[i].start();
            }
        }
    }

    public boolean shutDown(){
        try{
            for(Worker w: workers){

                w.thread.interrupt();

            }

            queue.clear();

            for(Thread workerThread : workerThreads){

                workerThread.interrupt();

            }

            return true;

        }catch(Exception e){
            LOG.debug(Thread.currentThread()+": Worker Thread Shutdown Failed");
            return false;

        }

    }

    private boolean isValidCount(int count){

        if(count<Integer.MAX_VALUE && count>0)
            return true;
        else
            return false;
    }

    private class Worker implements Runnable{

        final Thread thread;

        private Worker(){
            this.thread = Thread.currentThread();
        }

        @Override
        public void run() {
            try{
                while(true){
                    try{
                        Runnable r = queue.take();
                        r.run();
                    }catch(InterruptedException interrupt){
                        LOG.debug("Interrupted exception in: "+thread.getName());
                    }
                }
            }catch(Exception intr){

                this.thread.interrupt();

            }finally{

                this.thread.interrupt();
            }
        }
    }
}

您正在
while
循环中捕获异常

while (true) {
    try {
        Runnable r = queue.take();
        r.run();
    } catch (InterruptedException interrupt) {
        LOG.debug("Interrupted exception in: " + thread.getName());
    }
}
任何时候你中断这个线程,它都会再次循环。摆脱这个
试试catch
。让外部的一个(在
之外,而
)处理
中断异常

请注意,当线程执行
run()
时,您可能会得到
中断
,在这种情况下,
中断异常
可能不会达到预期效果。您可能应该设置一个标志,以便在
Runnable#run()
完成后,同一线程不会再次循环

我有一个线程池,它创建工人,工人从阻塞队列中获取作业。线程等待队列中的take()。即使显式调用运行线程的线程中断方法,它们仍然在等待take()。处理阻塞队列的正确方法是什么

在我看来,您正在复制
ExecutorService
的行为。这有什么原因吗?以下是:

有时,运行的线程需要保存上下文,但您的类似乎过于复杂。您仍然可以使用生产者线程和消费者线程之间共享
阻塞队列的
ExecutorService
。您可以在完成时中断线程,但也可以将
count
数量的
null
对象推入队列,并在工作线程看到
null
时退出

public class Worker implements Runnable {
     // some sort of context needed to be held by each runner
     public void run() {
         while (true) {
             Work work = sharedQueue.take();
             if (work == null) {
                 return;
             }
             // do the work ...
         }
     }
}

如何知道线程正在等待take()?在用remove()替换take时,线程按预期退出添加volatile标志有效,但这是处理线程关闭的正确方法吗?@arpitpanwar关闭线程池是一项非常重要的任务。查看
ThreadPoolExecutor
的源代码,了解一个复杂的示例。ExecutorService没有被使用,我想实现我自己的线程池。我纠正了这个问题,在队列中放入了一个对象,表示线程必须退出,并设置了一个标志,使线程中断while循环
ExecutorService threadPool = Executors.newFixedThreadPool(count);
...
threadPool.submit(new Runnable() ...);
public class Worker implements Runnable {
     // some sort of context needed to be held by each runner
     public void run() {
         while (true) {
             Work work = sharedQueue.take();
             if (work == null) {
                 return;
             }
             // do the work ...
         }
     }
}