java多线程中main主线程何时终止的问题 本帖最后由 zyw745293 于 2009-06-17 10:58:08 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 machine1.setPriority(1); 你设置下他们的优先级,在看看。 在if语句快后面加上一句打印的 你就知道怎么回事了 比如:System.out.println("执行"); 我照你说的做了,把原代码if语句块修改为if(++count%10==0){ log.append("\n"); System.out.println("执行"); }但现在其中一个结果如下(每次运行结果是不一样的), m2线程并没有执行. 而且"执行"并没按照我设置的每count%10才打印.main555执行m1:0 m1:1 m1:2 m1:3 m1:4 m1:5 m1:6 m1:7 m1:8 m1:9 执行执行执行 楼主理解错了,main方法里的print不一定是在最后执行,所以不会打印最终结果你在for循环后加上System.out.println(log);看看就知道了 线程基础...线程的运行顺序不可预知...你自己看你的程序啊..你开了两个子线程,这两个线程调用start方法后,并不是马上运行的线程的运行还要依赖于进程分配,实际上,线程启动更复杂,包含了资源分配,内存分配等等,这些动作都需要CPU时间的而main进程不管你的进程是不是在运行,它自己管自己的运行,很有可能在你log还没有并两个子线程写入的时候已经被打印了,当然什么东西都没有了 如果不对线程进行控制,线程运行顺序是不可预测的。就算做操作也只能进行大概的预测不能精确。main方法执行完后你的程序就退出了。当然那两个线程就得不到执行机会,你要把它设置成demo的线程。为什么log没有打印,不知道有没有人解答下?这个我不太清楚。。 setDaemon(boolean on)打错方法了。呵呵。不好意思。 在线程还没有执行之前,这行语句就已经执行过了。所以打印log时log里还没有内容,而不是没有打印。 楼主我试验了下。设置打Daemon线程也不行.hehe 因为你启动线程的时候run方法还没完成 所以会先调用 main()中的其他方法 System.out.println(main.getName()); System.out.println(main.getPriority()); System.out.println(machine1.getPriority()); System.out.println(machine2.getPriority()); System.out.println(log);这些会先执行因为log是空的所以不会打印出东西 public void run(){ for(int a = 0; a<20;a++){ log.append(currentThread().getName()+":"+a+" "); if(++count%10==0){ log.append("\n"); } } System.out.println(log); }把打印语句放到run方法中这样就可以看到效果了 设置优先级是起不到作用的,如果你其它线程耗的时间比较长,主线程很快就执行完了的话,可以采用在主线程使用wait等待,然后在子线程执行完的时候调用notify唤醒主线程。 你想交电脑界朋友嘛~我虽说称不上高手,但是对电脑的工作了如指掌,有空的朋友看看这个问题,我已经解决了,电脑开不开机,主机回转。但是显示器不会显示。http://net-ke.cn/0_5_101553.aspx 楼主的理解是对的,主线程(其实是进程)挂了,别的线程很可能没机会继续.所以你在主线程退出前,需要wait 楼主的理解是对的,主线程(其实是进程)挂了,别的线程很可能没机会开始.所以你在主线程退出前,需要wait,等待别的结束的信号过来后才能结束. 其实我们是可以控制主线程的运行顺序的,JAVA本身提供了这个控制机制。只要我们在machine1.start();machine2.start();这两句话后面追加:machine1.join();machine2.join();这两句话,那么主线程就会等待子线程运行完毕才会运行了。这是我们在编程中经常使用的控制方式^_^ 其实楼主要的答案很简单:程序在所有的非Daemon线程结束后终止。楼主之所以没有看到期望的打印结果,是因为main线程终止时,machine1/2还没来得及执行,不过在程序终止前终归是要执行的。(另外,多运行几次,有时能看到预期结果)我改了下程序:public class Machine extends Thread{ // private static StringBuffer log = new StringBuffer(); private static int count = 0; public void run() { StringBuffer log = new StringBuffer(); for (int a = 0; a < 20; a++) { log.append(currentThread().getName() + ":" + a + " "); if (++count % 10 == 0) { log.append("\n"); } } System.out.println(log); } public static void main(final String[] args) { Thread main = Thread.currentThread(); System.out.println(main.getName()); Machine machine1 = new Machine(); Machine machine2 = new Machine(); machine1.setDaemon(false);// 强调一下,默认就是false machine2.setDaemon(false); machine1.setName("m1"); machine2.setName("m2"); machine1.start(); machine2.start(); // try // { // Thread.sleep(2000); // } // catch (Exception e) // { // e.printStackTrace(); // } System.out.println(main.getPriority());// 打印主线程优先级 System.out.println(machine1.getPriority());// 打印m1线程优先级 System.out.println(machine2.getPriority());// 打印m2线程优先级 }} 可以通过判断线程状态 所有线程都已运行 再结束mainfor(int i=0;i<count;i++){ if(parseThread[i].getState().name().equals("WAITING")){ Thread.sleep(50); i--; }} cpu问题 关键不知道线程什么时候才能执行 public class Machine extends Thread{ private static StringBuffer log = new StringBuffer(); private static int count = 0 ; public void run(){ for(int a = 0; a<20;a++){ log.append(currentThread().getName()+":"+a+" "); if(++count%10==0){ log.append("\n"); } } } public static void main(String[] args) { Thread main = Thread.currentThread(); System.out.println(main.getName()); Machine machine1 = new Machine(); Machine machine2 = new Machine(); machine1.setName("m1"); machine2.setName("m2"); machine1.start(); machine2.start(); /* try { Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } */ try { machine1.join();//等待m1线程结束 machine2.join();//等待m2线程结束,主线程继续向下执行 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(main.getPriority());//打印主线程优先级 System.out.println(machine1.getPriority());//打印m1线程优先级 System.out.println(machine2.getPriority());//打印m2线程优先级 System.out.println(log); }}main555m2:0 m1:0 m2:1 m1:1 m2:2 m1:2 m2:3 m1:3 m2:4 m1:4 m2:5 m1:5 m2:6 m1:6 m2:7 m1:7 m2:8 m1:8 m2:9 m1:9m2:10 m1:10 m2:11 m2:12 m1:11 m2:13 m1:12 m2:14 m1:13 m2:15 m1:14 m2:16 m1:15 m2:17 m1:16 m2:18 m1:17 m2:19 m1:18 m1:19 如果不等待子线程结束,很有可能在主线程执行完System.out.println(log);后还没向log写入,或者只写入了一部分,主要是没对3个线程的进度进行控制引起的,所以上面的输出顺序每次都有可能不同。另外,即使没有machine1.join();语句,主线程也会在执行完自己的任务后等待子线程结束之后再退出,不会存在来不及执行的情况 这个问题应该和Daemon没有关系。虚拟机规范规定虚拟机推出的前提是所有非daemon线程退出。这里main,m1,m2都是非daemon线程,所以虚拟机一定会等他们退出的。如果把这个程序稍微做一点修改,把run()里的log改成 System.out.print,那么可以看到,m1和m2总是会打印的。 public void run() { for (int a = 0; a < 20; a++) { System.out.print(currentThread().getName() + ":" + a + " "); //log.append(currentThread().getName() + ":" + a + " "); if (++count % 10 == 0) { System.out.println(); // log.append("\n"); } } }那么问题出在哪里呢?看样子是log的问题了。实例log是StringBuffer类型的,那么这个程序作了什么呢?log是一个StringBuffer类型的一个static变量,在多个线程中间都可以被操作。m1和m2做的事情是append 往log里追加内容,但这些内容直到main线程退出之前最后一行才打印,因为log不是被同步的,所以main退出的时候m1和m2还没来得及往log里写内容,所以这个时候log是空的,实际上确实是打印了,只是内容是空的。m1和m2等main退出后呢,也确实给log追加内容了,但只是没有打印而已。 问题:以上代码中创建了m1、m2线程,还有本身的线程main,为什么使用了try代码块中的主线程休眠才可以看到m1、m2执行run()方法的结果?而将try block注释掉之后m1、m2的run()似乎没怎么执行。 个人理解似乎是main主线程急于结束,没能给m1、m2线程执行的机会。但按道理应该是m1、m2并发执行,main()也不应该干涉它们的执行啊。 请高手指教?答案:你说的有道理,你的程序确实创建了三个非deamon线程,且互不干扰。没有结果输出的主要原因是:1.JVM从main方法开始执行,这是主线程。2.同时创建了两个线程m1,m2并启动线程,在启动过程中有JVM调度到就绪队列中等待CPU的分配。3.主线程继续往下执行,由于线程的调度是需要时间的。m1,m2线程还没执行完,主线程就执行了打印操作。4.所以你最终看到的结果是还没执行完的结果。 37楼正解,楼主不妨把打印语句写在run方法里看下就知道了。 正确,执行 System.out.println(log);的时候log还没有东西 楼主的验证方法有问题,因为log有可能为空,因为main早于另外两个线程执行 楼上你还关注啥啊,已经有正确答案了,就是join,前面代码都有啦 主线程中只是负责启动了两个子线程,并不负责将两个子线程都运行结束自己才结束。也就是说,两个子线程还没有启动运行时,那句println(log)已经走过去了,此时的log啥都没有,当然打印结果也是啥都没有喽。应该将println() 写到子线程重写的run方法里面去。 楼上说得比较全了,log确实被打印了,通过这种方式可以看到现象System.out.println(main.getPriority());// 打印主线程优先级System.out.println(machine1.getPriority());// 打印m1线程优先级System.out.println(machine2.getPriority());// 打印m2线程优先级System.out.println(log);System.out.println("结束");结果是:555结束明显有个回行,说明log被打印了,只是log为空而已!我的想法是:当执行main是创建主线程,执行期间又创建两个线程m1,m2,并且m1,m2开始等待cup调度运行,此时主线程继续向下运行,直接打印log,所以m1,m2未来及时更新log的内容,之后更新完也不能再打印!!! linux中如何用Java读一个EXE的版本号 求助关于JNDI 初学Java 求Thinking in java第三版(中文)书上例子的源代码 java中有什么专门处理矩阵的包吗? 如何用时间创建目录 xiaoxhui(飞)请来接分,只有20分了 xiewei请进领分2 关于Swing powerJ 沒錯誤但跑的時候出錯~可以幫我看看哪裡出問題了嗎? 断点续传时先测出已下载文件的大小,再用InputStream的skip()跳转可以吗?
log.append("\n");
System.out.println("执行");
}但现在其中一个结果如下(每次运行结果是不一样的), m2线程并没有执行. 而且"执行"并没按照我设置的每count%10才打印.
main
5
5
5
执行
m1:0 m1:1 m1:2 m1:3 m1:4 m1:5 m1:6 m1:7 m1:8 m1:9 执行
执行
执行
你在for循环后加上
System.out.println(log);
看看就知道了
线程的运行顺序不可预知...
你自己看你的程序啊..
你开了两个子线程,这两个线程调用start方法后,并不是马上运行的
线程的运行还要依赖于进程分配,实际上,线程启动更复杂,包含了资源分配,内存分配等等,这些动作都需要CPU时间的
而main进程不管你的进程是不是在运行,它自己管自己的运行,很有可能在你log还没有并两个子线程写入的时候已经被打印了,当然什么东西都没有了
main方法执行完后你的程序就退出了。当然那两个线程就得不到执行机会,你要把它设置成demo的线程。为什么log没有打印,不知道有没有人解答下?这个我不太清楚。。
打错方法了。
呵呵。不好意思。
在线程还没有执行之前,这行语句就已经执行过了。所以打印log时log里还没有内容,而不是没有打印。
设置打Daemon线程也不行.
hehe
System.out.println(main.getName());
System.out.println(main.getPriority());
System.out.println(machine1.getPriority());
System.out.println(machine2.getPriority());
System.out.println(log);
这些会先执行因为log是空的所以不会打印出东西
public void run(){
for(int a = 0; a<20;a++){
log.append(currentThread().getName()+":"+a+" ");
if(++count%10==0){
log.append("\n");
}
}
System.out.println(log);
}
把打印语句放到run方法中这样就可以看到效果了
所以你在主线程退出前,需要wait
所以你在主线程退出前,需要wait,等待别的结束的信号过来后才能结束.
machine1.start();
machine2.start();
这两句话后面追加:
machine1.join();
machine2.join();
这两句话,那么主线程就会等待子线程运行完毕才会运行了。这是我们在编程中经常使用的
控制方式^_^
楼主之所以没有看到期望的打印结果,是因为main线程终止时,machine1/2还没来得及执行,不过在程序终止前终归是要执行的。(另外,多运行几次,有时能看到预期结果)
我改了下程序:
public class Machine extends Thread
{
// private static StringBuffer log = new StringBuffer(); private static int count = 0; public void run()
{
StringBuffer log = new StringBuffer();
for (int a = 0; a < 20; a++)
{
log.append(currentThread().getName() + ":" + a + " ");
if (++count % 10 == 0)
{
log.append("\n");
} }
System.out.println(log);
} public static void main(final String[] args)
{
Thread main = Thread.currentThread();
System.out.println(main.getName());
Machine machine1 = new Machine();
Machine machine2 = new Machine();
machine1.setDaemon(false);// 强调一下,默认就是false
machine2.setDaemon(false);
machine1.setName("m1");
machine2.setName("m2");
machine1.start();
machine2.start(); // try
// {
// Thread.sleep(2000);
// }
// catch (Exception e)
// {
// e.printStackTrace();
// } System.out.println(main.getPriority());// 打印主线程优先级
System.out.println(machine1.getPriority());// 打印m1线程优先级
System.out.println(machine2.getPriority());// 打印m2线程优先级 }
}
if(parseThread[i].getState().name().equals("WAITING")){
Thread.sleep(50);
i--;
}
}
public class Machine extends Thread{
private static StringBuffer log = new StringBuffer();
private static int count = 0 ;
public void run(){
for(int a = 0; a<20;a++){
log.append(currentThread().getName()+":"+a+" ");
if(++count%10==0){
log.append("\n");
}
}
}
public static void main(String[] args) {
Thread main = Thread.currentThread();
System.out.println(main.getName());
Machine machine1 = new Machine();
Machine machine2 = new Machine();
machine1.setName("m1");
machine2.setName("m2");
machine1.start();
machine2.start();
/* try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
*/
try {
machine1.join();//等待m1线程结束
machine2.join();//等待m2线程结束,主线程继续向下执行
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(main.getPriority());//打印主线程优先级
System.out.println(machine1.getPriority());//打印m1线程优先级
System.out.println(machine2.getPriority());//打印m2线程优先级
System.out.println(log);
}
}
main
5
5
5
m2:0 m1:0 m2:1 m1:1 m2:2 m1:2 m2:3 m1:3 m2:4 m1:4
m2:5 m1:5 m2:6 m1:6 m2:7 m1:7 m2:8 m1:8 m2:9 m1:9
m2:10 m1:10 m2:11 m2:12 m1:11 m2:13 m1:12 m2:14 m1:13 m2:15
m1:14 m2:16 m1:15 m2:17 m1:16 m2:18 m1:17 m2:19 m1:18 m1:19
如果不等待子线程结束,很有可能在主线程执行完System.out.println(log);后还没向log写入,
或者只写入了一部分,主要是没对3个线程的进度进行控制引起的,所以上面的输出顺序每次都
有可能不同。另外,即使没有machine1.join();语句,主线程也会在执行完自己的任务后等待
子线程结束之后再退出,不会存在来不及执行的情况
如果把这个程序稍微做一点修改,把run()里的log改成 System.out.print,那么可以看到,m1和m2总是会打印的。
public void run() {
for (int a = 0; a < 20; a++) {
System.out.print(currentThread().getName() + ":" + a + " ");
//log.append(currentThread().getName() + ":" + a + " ");
if (++count % 10 == 0) {
System.out.println();
// log.append("\n");
}
}
}那么问题出在哪里呢?看样子是log的问题了。
实例log是StringBuffer类型的,那么这个程序作了什么呢?
log是一个StringBuffer类型的一个static变量,在多个线程中间都可以被操作。m1和m2做的事情是append 往log里追加内容,但这些内容直到main线程退出之前最后一行才打印,因为log不是被同步的,所以main退出的时候m1和m2还没来得及往log里写内容,所以这个时候log是空的,实际上确实是打印了,只是内容是空的。m1和m2等main退出后呢,也确实给log追加内容了,但只是没有打印而已。
以上代码中创建了m1、m2线程,还有本身的线程main,为什么使用了try代码块中的主线程休眠才可以看到m1、m2执行run()方法的结果?而将try block注释掉之后m1、m2的run()似乎没怎么执行。 个人理解似乎是main主线程急于结束,没能给m1、m2线程执行的机会。但按道理应该是m1、m2并发执行,main()也不应该干涉它们的执行啊。 请高手指教?答案:
你说的有道理,你的程序确实创建了三个非deamon线程,且互不干扰。没有结果输出的主要原因是:
1.JVM从main方法开始执行,这是主线程。
2.同时创建了两个线程m1,m2并启动线程,在启动过程中有JVM调度到就绪队列中等待CPU的分配。
3.主线程继续往下执行,由于线程的调度是需要时间的。m1,m2线程还没执行完,主线程就执行了打印操作。
4.所以你最终看到的结果是还没执行完的结果。
正确,执行 System.out.println(log);的时候log还没有东西
log确实被打印了,通过这种方式可以看到现象
System.out.println(main.getPriority());// 打印主线程优先级
System.out.println(machine1.getPriority());// 打印m1线程优先级
System.out.println(machine2.getPriority());// 打印m2线程优先级
System.out.println(log);
System.out.println("结束");
结果是:
5
5
5结束明显有个回行,说明log被打印了,只是log为空而已!我的想法是:当执行main是创建主线程,执行期间又创建两个线程m1,m2,并且m1,m2开始等待cup调度运行,此时主线程继续向下运行,直接打印log,所以m1,m2未来及时更新log的内容,之后更新完也不能再打印!!!