在线程池中中断BlockingQueue take()

时间:2015-01-12 16:31:22

标签: java multithreading threadpool blockingqueue

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

的正确方法
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();
            }
        }
    }
}

通话类:

public class Runner {
    public static void main(String[] args) {
        try {
            System.out.println("BeforeLaunch");
            ThreadPoolGen gen = new ThreadPoolGen(10);
            gen.execute(new Runnable() {

                @Override
                public void run() {
                    System.out.println("Inside Runnable");

                }
            });

            gen.shutDown();
        } catch (CountException ce) {
        } catch (Exception e) {
        }

    }

}

2 个答案:

答案 0 :(得分:1)

您正在while循环

中捕获异常
while (true) {
    try {
        Runnable r = queue.take();
        r.run();
    } catch (InterruptedException interrupt) {
        LOG.debug("Interrupted exception in: " + thread.getName());
    }
}

每次中断此线程时,它都会再次循环。摆脱这个try-catch。让外部的(while之外)处理InterruptedException

请注意,在线程执行interrupt时,您可能会获得run(),在这种情况下,InterruptedException可能无法达到预期效果。你应该设置一个标志,这样一旦完成Runnable#run(),同一个线程就不会再循环。

答案 1 :(得分:1)

  

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

在我看来,您正在复制ExecutorService的行为。是否有一个原因?这是tutorial for them

ExecutorService threadPool = Executors.newFixedThreadPool(count);
...
threadPool.submit(new Runnable() ...);

有时需要由正在运行的线程保存上下文,但看起来您的类似乎过于复杂。您仍然可以使用在生产者和使用者线程之间共享ExecutorService的{​​{1}}。您可以在完成后中断线程,但也可以将BlockingQueuecount个对象放入队列,并在看到null时让工作线程退出。

null