Java 为什么有这么多等待线程?

Java 为什么有这么多等待线程?,java,multithreading,Java,Multithreading,我有一个简单的程序,有一个定时任务,可以触发一些计算 在这个过程的最后,仍然有很多定时等待和等待队列,这是我没有预料到的 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 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])
我想知道为什么,这种情况的风险是什么,以及如何预防(例如,有一个良好的终止)

公共类SimpleMain{
静态列表模块;
静态执行器服务执行器单计算;
静态ScheduledExecutorService executorCompute;
静态ScheduledFuture sfc=null;
/**
*@param指定命令行参数
*/
公共静态void main(字符串[]args){
modules=newarraylist();
添加(新的SimpleModule(“A”,1_000));
添加(新的SimpleModule(“B”,2_000));
添加(新的SimpleModule(“C”,350));
添加(新的SimpleModule(“D”,20));
添加(新的SimpleModule(“E”,600));
//-计算线程
//(daemon=false)
ThreadFactory threadFacoryCompute=新的MyThreadFactory(“计算”,Thread.NORM\u PRIORITY,false);
ExecutoryCompute=新的ScheduledThreadPoolExecutor(1,threadFacoryCompute);
executorSingleCompute=新线程池执行器(0,Integer.MAX_值,
60升,时间单位。秒,
新建SynchronousQueue(),threadFacoryCompute);
//--开始--
sfc=ExecuteCompute.scheduleAtFixedRate(新的ComputeRead(),0,50,时间单位为毫秒);
//--演奏--
试一试{
睡眠(20_000);
}捕获(中断异常例外){
例如printStackTrace();
}
//--最后的停顿--
证监会:撤销(虚假);
试一试{
布尔状态=ExecuteCompute.awaitTermination(1000,时间单位为毫秒);
System.out.printf(“计算执行器已终止:%b\n”,状态);
}捕获(中断异常例外){
System.out.printf(“计算执行器中断\n”);
}
试一试{
布尔状态=executorSingleCompute.awaitTermination(1000,时间单位为毫秒);
System.out.printf(“单个计算执行器已终止:%b\n”,状态);
}捕获(中断异常例外){
System.out.printf(“单个计算执行器中断\n”);
}
//调试
Thread.getAllStackTraces().keySet().stream()
.filter(t->(“compute”.equals(t.getThreadGroup().getName()))
.forEach(t->System.out.printf(“==线程\%s\”:%s(%s)\n)、t.getName()、t.getState().toString()、t.getThreadGroup());
系统出口(0);
}
//科雷亚茨特
公共静态类ComputeThread实现可运行{
@凌驾
公开募捐{
long now=System.currentTimeMillis();
用于(模块:模块){
Runnable Runnable=()->{
计算模块(现在);
};
executorSingleCompute.submit(可运行);
}
}
}
/**
*联合国螺纹工厂
*/
私有静态类MyThreadFactory实现ThreadFactory{
私人团体;
公共MyThreadFactory(字符串名称、int优先级、布尔守护进程){
组=新线程组(名称);
组。setMaxPriority(优先级);
setDaemon(守护进程);
}
长cnt=0;
@凌驾
公共线程newThread(可运行的r){
线程t=新线程(组,r,“线程-”+group.getName()+“-”+cnt++);
返回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();
        }
    }

}
公共类SimpleModule{
private final Lock computeLock=new ReentrantLock();
私有最终字符串名;
私人最终长期合同;
私人长期延期=-1;
公共SimpleModule(字符串名称,长持续时间){
this.name=名称;
这个。持续时间=持续时间;
}
公共void计算(长时间){
if(computeLock.tryLock()){
//重作业
对于(int i=0;i
完成后,您会调用
等待终止
,但您从不调用
关机
立即关机
,只会等待一秒钟。线还在那里。要完全终止,请先调用
shutdown
(或
shutdownNow
)。然后,您可以调用
等待终止
,并根据您的作业所需的时间设置适当的时间限制。这样做,线程就应该消失了


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

是否有不使用
执行器的原因。newCachedThreadPool(..)
我认为SynchronousQueue将阻止线程,直到为
executorSingleCOmpute“添加”新的内容为止?我的语句与
newCachedThreadPool
等效,只是我强制使用优先级较低的特定线程组。太好了。我不理解那种
shutdown()
doc。如果我想重新启动一切,我有一个错误。我需要重新创建新的遗嘱执行人吗?是的。或者,如果您计划重用它们并仅在即将退出时关闭它们,请让它们运行(使用等待线程)。
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();
        }
    }

}