【问题标题】:Java thread executor never shuts down?Java线程执行器永远不会关闭?
【发布时间】:2016-10-25 00:14:22
【问题描述】:

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

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! ");
            }
        }
    }
}

【问题讨论】:

    标签: java multithreading threadpool executorservice


    【解决方案1】:

    在几个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 {
    

    【讨论】:

    • 我在队列中添加了一颗毒丸,但线程仍然不会自行死亡!有什么想法吗?
    【解决方案2】:

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

    线程将一直等待,直到它被中断。 Executor 将一直等到其线程完成。

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

    看来您必须使用 files.poll() 而不是 files.take() - 它不会锁定空队列 @9​​87654328@。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-01
      • 2011-06-26
      • 1970-01-01
      • 1970-01-01
      • 2020-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多