Why so many TIMED_WAITING threads?

问题: I've got a simple programs with a scheduled task that triggers some computation. In the end of the process, there are still a lot of TIMED_WAITING and WAITING queues, wh...

问题:

I've got a simple programs with a scheduled task that triggers some computation.

In the end of the process, there are still a lot of TIMED_WAITING and WAITING queues, what I didn't expected.

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])

I wonder why, what's the risk of this and how to prevent it (i.e. having a good termination).

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: %bn", status);
        } catch (InterruptedException ex) {
            System.out.printf("Compute Executor interruptedn");
        }

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

        // 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;

        }
    }
}

And the module class:

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:

When you are done you call awaitTermination, but you never call shutdown or shutdownNow and you only wait for a second. The threads are still there. To terminate cleanly, call shutdown first (or shutdownNow). Then you can call awaitTermination with a suitable time limit that depends on how long your jobs can take. Do that and the threads should be gone!

EDIT: you need to call shutdown on both executors, of course.

  • 发表于 2019-02-21 07:35
  • 阅读 ( 289 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除