为什么会有这么多TIMED_WAITING线程?

时间:2019-02-19 21:47:27

标签: 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();
        }
    }

}

1 个答案:

答案 0 :(得分:2)

完成后,您致电awaitTermination,但从未致电shutdownshutdownNow,而只等了一秒钟。线程仍然在那里。要完全终止,请先致电shutdown(或shutdownNow)。然后,您可以在适当的时限内致电awaitTermination,具体时限取决于您的工作需要多长时间。这样做,线程应该消失了!

编辑:您当然需要在两个执行器上都调用shutdown。