我有以下代码,我希望最后打印“DONE”。但是当我跑步时,“DONE”从未被打印过,而JVM实际上从未终止过。
我做错了什么?
// File: Simple.java
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Simple {
public static void main(String[] args) throws Exception{
doTest(3);
}
private static void doTest(final int times) {
ScheduledExecutorService tp = Executors.newScheduledThreadPool(times);
Thread[] runnables = new Thread[times];
for (int i = 0; i < runnables.length; ++i) {
runnables[i] = new Thread(new MyRunnable());
}
// schedule for them all to run
for (Thread t : runnables) {
tp.schedule(t, 1, TimeUnit.SECONDS);
}
try {
tp.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
System.out.println("DONE!");
}catch (InterruptedException e) {
e.printStackTrace();
}
}
static class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("hello world");
}
}
}
答案 0 :(得分:2)
这里有两件事你做错了。
首先,如果您使用的是ExecutorService
,那么您也不应该创建自己的线程。只需将Runnables直接提交给执行程序 - 执行程序服务就有自己的线程集合,并运行您在自己的线程上提交的任何内容,因此您创建的线程甚至无法启动。
其次,如果你已经完成了ExecutorService,并且要等到它终止,你需要在提交上一份工作后在执行者服务上调用shutdown()
。
答案 1 :(得分:0)
您忘了shutdown ExecutorService
:
tp.shutdown(); // <-- add this
tp.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
另外我应该提一下,创建Thread
以将它们用作Runnable
s不仅毫无意义,而且可能会产生误导。对于Runnable
变量,您应该使用Thread
而不是runnables
。
Runnable[] runnables = new Runnable[times];
答案 2 :(得分:0)
Executors.newScheduledThreadPool(times)
对其ThreadFactory使用Executors.defaultThreadFactory()。
当Java虚拟机启动时,通常只有一个 非守护程序线程(通常调用名为main的方法) 指定班级)。 Java虚拟机继续执行 线程,直到发生以下任一情况:
- 已调用类Runtime的exit方法,安全管理器已允许退出操作。
- 所有非守护程序线程的线程都已死亡,无论是通过调用run方法返回还是抛出异常 传播超出run方法。
所以,这就是你所拥有的;但我改变了3件事。
最后,你告诉它要永远等待使用Long.MAX。但我认为你这样做是因为关机感觉它现在会关闭。但事实并非如此。
public static void main(String[] args) throws Exception {
doTest(3);
}
private static void doTest(final int times) {
ScheduledExecutorService tp = Executors.newScheduledThreadPool(times);
Thread[] runnables = new Thread[times];
for (int i = 0; i < runnables.length; ++i) {
runnables[i] = new Thread(new MyRunnable());
}
// schedule for them all to run
int i = 1;
for (Thread t : runnables) {
tp.schedule(t, i++, TimeUnit.SECONDS);
}
System.out.println("Calling shutdown");
tp.shutdown();
}
static class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("hello world");
}
}
希望能回答你的问题。现在,你有点复制东西。
如果你打算使用executerservice
,你应该告诉它为你安排一些事情。
public static void main(String[] args) throws Exception {
doTest(3);
}
private static void doTest(final int times) {
ScheduledExecutorService tp = Executors.newScheduledThreadPool(times);
for (int i = 0; i < times; ++i) {
tp.schedule(new MyRunnable(), 1, TimeUnit.SECONDS);
}
System.out.println("Calling shutdown");
tp.shutdown();
}
static class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("hello world");
}
}