Java线程执行器永远不会关闭?

时间:2016-06-22 21:20:04

标签: java multithreading threadpool executorservice

我遵循将一些数据放入阻塞队列的代码,并根据固定的线程池将线程任务提交给Java executor服务。当我尝试关闭执行程序虽然它没有关闭时,请问有什么想法吗?

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ThreadExecutir {
    public static ArrayBlockingQueue<String> files;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        shutdownExec();
    }

    private static void shutdownExec() {
        int size = 10;
        files = new ArrayBlockingQueue<String>(100);
        for (int i = 0; i < 5; i++) {
            files.add("Java " + i);
        }

        ThreadExecutir outer = new ThreadExecutir();
        ExecutorService executor = Executors.newFixedThreadPool(size);
        for (int i = 0; i < 3 * size; i++) {
            executor.submit(outer.new myThread());
        }
        System.out.println(executor.isShutdown());
        executor.shutdown();

        try {
            executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
            System.out.println("Awaiting for threads to complete!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (files.isEmpty())
            executor.shutdownNow();
        System.out.println(executor.isShutdown());

    }

    class myThread extends Thread {
        public void run() {

            String threadName = Thread.currentThread().getName();
            System.out.println("Thread " + threadName + "started running! ");
            try {
                String uploadThis = files.take();
                System.out.println("I'm working " + threadName + " "
                        + uploadThis);
                // this.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                System.out.println("Thread " + threadName
                        + " finished running! ");
            }
        }
    }
}

2 个答案:

答案 0 :(得分:4)

在几个myThread个实例消耗了files中的所有元素后,files.take()上的其余部分就停止了。

shutdown州的javadoc

  

启动以前提交的任务的有序关闭   已执行,但不会接受任何新任务。调用没有   如果已经关闭,则会产生额外的影响。

在致电shutdown之前,您已经提交了所有30项任务(其中10项正在执行)。所以他们都需要在ExecutorService被视为终止之前完成执行。但是他们中的大多数都无法完成执行,因为现在没有任何东西可以让他们在take()停止阻止。

您需要向ArrayBlockingQueue提交更多项目或中断ExecutorService中的主题。 shutdownNow可用于中断这些线程。

请注意,中断可能不足以阻止线程,因为中断可能会在阻塞调用之前到达。您需要更多sophisticated solution, like a poison pill

虽然你已经将Thread

分组了
class myThread extends Thread {

您仅将myThread用作RunnableThread实施Runnable)。这是毫无意义的。只需实施Runnable

即可
class myThread implements Runnable {

答案 1 :(得分:1)

您只向队列提交了5个字符串,并提交了30个任务。前5个任务使用来自files的所有5个字符串,并且阻止下一个字符串尝试从空队列中poll()字符串(在队列上调用notEmpty.await())。

线程将一直等到它被中断。执行程序将等待其线程完成。

因此代码将停留在executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)上,永远不会到达if (files.isEmpty()) executor.shutdownNow();

您似乎必须使用files.poll()代替files.take() - 它不会锁定空队列return (count == 0) ? null : dequeue();