java - 为什么有这么多 TIMED_WAITING 线程?

标签 java multithreading

我有一个简单的程序,其中包含触发一些计算的计划任务。

在流程结束时,仍然有很多TIMED_WAITING和WAITING队列,这是我没想到的。

Compute Executor terminated: false
Individual Compute Executor terminated: false
== Thread "thread-compute-6": TIMED_WAITING (java.lang.ThreadGroup[name=compute,maxpri=5])
== Thread "thread-compute-4": TIMED_WAITING (java.lang.ThreadGroup[name=compute,maxpri=5])
== Thread "thread-compute-1": TIMED_WAITING (java.lang.ThreadGroup[name=compute,maxpri=5])
== Thread "thread-compute-2": TIMED_WAITING (java.lang.ThreadGroup[name=compute,maxpri=5])
== Thread "thread-compute-0": WAITING (java.lang.ThreadGroup[name=compute,maxpri=5])
== Thread "thread-compute-5": TIMED_WAITING (java.lang.ThreadGroup[name=compute,maxpri=5])
== Thread "thread-compute-3": TIMED_WAITING (java.lang.ThreadGroup[name=compute,maxpri=5])

我想知道为什么,这样做的风险是什么以及如何防止它(即有一个好的终止)。

public class SimpleMain {

    static List<SimpleModule> modules;

    static ExecutorService executorSingleCompute;
    static ScheduledExecutorService executorCompute;

    static ScheduledFuture<?> sfc = null;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        modules = new ArrayList<>();
        modules.add(new SimpleModule("A", 1_000));
        modules.add(new SimpleModule("B", 2_000));
        modules.add(new SimpleModule("C", 350));
        modules.add(new SimpleModule("D", 20));
        modules.add(new SimpleModule("E", 600));

        // - Compute Threads
        // (daemon=false)
        ThreadFactory threadFacoryCompute = new MyThreadFactory("compute",Thread.NORM_PRIORITY,false);
        executorCompute = new ScheduledThreadPoolExecutor(1, threadFacoryCompute);

        executorSingleCompute = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                60L, TimeUnit.SECONDS,
                new SynchronousQueue<>(), threadFacoryCompute);

        // -- START --
        sfc = executorCompute.scheduleAtFixedRate(new ComputeThread(), 0, 50, TimeUnit.MILLISECONDS);

        // -- PLAYING --
        try {
            Thread.sleep(20_000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }

        // -- FINAL PAUSE --
        sfc.cancel(false);

        try {
            boolean status = executorCompute.awaitTermination(1000, TimeUnit.MILLISECONDS);
            System.out.printf("Compute Executor terminated: %b\n", status);
        } catch (InterruptedException ex) {
            System.out.printf("Compute Executor interrupted\n");
        }

        try {
            boolean status = executorSingleCompute.awaitTermination(1000, TimeUnit.MILLISECONDS);
            System.out.printf("Individual Compute Executor terminated: %b\n", status);
        } catch (InterruptedException ex) {
            System.out.printf("Individual Compute Executor interrupted\n");
        }

        // Debug
        Thread.getAllStackTraces().keySet().stream()
                .filter(t->("compute".equals(t.getThreadGroup().getName())))
                .forEach(t -> System.out.printf("== Thread \"%s\": %s (%s)\n", t.getName(), t.getState().toString(), t.getThreadGroup()));

        System.exit(0);

    }

    // Threads pour CoreAtvste
    public static class ComputeThread implements Runnable {

        @Override
        public void run() {
            long now = System.currentTimeMillis();
            for (Module module : modules) {
                Runnable runnable = () -> {
                    module.compute(now);
                };
                executorSingleCompute.submit(runnable);
            }

        }
    }
    /**
     * Une threadFactory
     */
    private static class MyThreadFactory implements ThreadFactory {

        private final ThreadGroup group;

        public MyThreadFactory(String name, int priority, boolean daemon) {
            group = new ThreadGroup(name);
            group.setMaxPriority(priority);
            group.setDaemon(daemon);
        }

        long cnt = 0;

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r, "thread-" + group.getName() + "-" + cnt++);
            return t;

        }
    }
}

和模块类:

public class SimpleModule {

    private final Lock computeLock = new ReentrantLock();

    private final String name;
    private final long duration;


    private long lastOuts = -1;

    public SimpleModule(String name, long duration) {
        this.name = name;
        this.duration = duration;
    }

    public void compute(long when) {

        if (computeLock.tryLock()) {

            // Heavy operation
            for (int i = 0; i < duration * 50; i++) {
                Math.random();
            }

            computeLock.unlock();
        }
    }

}

最佳答案

完成后,您会调用 awaitTermination,但您不会调用 shutdownshutdownNow,而只会等待一秒钟。线程仍然存在。要彻底终止,请先调用 shutdown (或 shutdownNow)。然后,您可以调用 awaitTermination 并设置合适的时间限制,具体取决于您的作业需要多长时间。这样做,线程就会消失!

编辑:当然,您需要在两个执行器上调用关闭。

关于java - 为什么有这么多 TIMED_WAITING 线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54775452/

相关文章:

java - JDBC MySQL URL 和特殊字符的问题

java - java.time API 如何确定政府对区域规则的更改?

java - 这段代码如何以及为什么是线程安全的……?

java - 安全访问多线程HashMap Java

ruby - `loop{}` 与 `loop{sleep 1}`

javascript - 如何在 TypeScript 中使用泛型模拟 Java 类文字?

java - 为什么 Jackson 中的 JsonGeneratorDelegate 没有实现 setPrettyPrinter() ?

java - 从多个应用程序/进程记录到单个日志文件

java - Perl 与 Java 中的多线程

c++ - std::thread::hardware_concurrency 和静态初始化