2013-08-07 82 views
2

我正在研究线程连接()方法,我碰到了stackoverflow上的ThreadJoinMethod后 。我修改了代码来开发一个工作示例,我对 输出感到困惑。代码片段是。线程连接()方法输出混淆

class JoinRunnable implements Runnable{ 

    public void run() { 
    for(int i =0 ; i < 4 ; i++){ 
     System.out.println(i); 
    } 
    } 
} 
public class TestJoin{ 
    public static void main(String[] args) throws InterruptedException { 
    JoinRunnable joinRunnable = new JoinRunnable(); 
    Thread t1 = new Thread(joinRunnable); 
    Thread t2 = new Thread(joinRunnable); 
    t1.start(); 
    t2.start(); 
    System.out.println("Currently running thread: " + Thread.currentThread().getName()); 
    t1.join(); 
    t2.join(); 
    System.out.println("I must wait"); 
    } 
} 

以下程序的输出是: -

0 
1 
2 
3 
0 
1 
2 
3 
Currently running thread: main 
I must wait 

我在输出困惑。当前线程将在t1 和t2上调用join后加入,但为什么在t1和t2 完成后语句"Currently Running Thread: main"正在打印?我在这里错过了一些重要的概念吗?因为main()会在 之后加入t1和t2之前的连接语句。有人可以详细说明吗?

+0

其他两个线程是否可能在调用'Thread','System','out'等各个库之前调用它们的过程来产生结果?测试,通过为每个人输出1到10000,然后通过筛选获得乐趣。 – christopher

+2

在循环迭代中添加睡眠,您将看到不会得到相同的结果。 –

+0

完美,我刚刚添加睡眠现在正在运行的方法main被首先打印。所以输出必须不同。万分感谢。 – benz

回答

4

线程在您致电start()后启动这意味着它可以在任何行之后开始,甚至可以在它之后的行之前完成。

1

这只是运行得太快。在这两个线程中插入一个短暂的睡眠。

2

你正在解释错误的方式。 join()方法导致main线程等待t1t2。因此main在完成t1t2之前不会退出。首先打印的内容完全是任意的,主要取决于线程的优先级。要设置预定义的行为,您必须同步这些线程。

+0

我想你实际上把问题解释错了。 –

+0

但是,t1和t2不会进入运行状态,并且此语句显示“Currnetly running thread main”。是吗? – benz

+0

@RohitJain再次阅读,他说主线程将被连接(意味着它将等待)。 – user2550754

1

这里是join()方法的描述:
Blocks the current Thread (Thread.currentThread()) until the receiver finishes its execution and dies.(从的javadoc)
事实上,你可能会阻止它正在等待T1 T2 &停止你的主线程。

+0

但是,t1和t2不会进入运行状态,并且此语句显示“Currnetly running thread main”。是吗? – benz

+0

我认为Peter Lawrey的评论与你的问题比我的更相关,我认为你应该增加一些短暂的睡眠(如上所述),看t1和t2的过程是否在此之前完成。 – Sw4Tish

+0

谢谢@ Sw4Tish。我这样做了,这次输出不一样。 – benz

2

System.out.println在基础OutputStream实例上同步(至少在我的PC上的实现中)。每个println之间的时间间隔非常短,所以来自另一个线程的println不太可能有机会被执行。所以看起来你在println上有一定的顺序(至少很有可能)。插入一些睡觉,让循环数更高,你应该能够观察到不同的行为。

+0

谢谢非常多的人。我在这里理解了这个概念。 – benz

1

线程T1和T2开始,你的发言之前,完成了他们的工作

System.out.println("Currently running thread: " + Thread.currentThread().getName()); 

实际上可以产生上screen.So线程T1和T2的任何输出都已经完成了他们的任务,主线程可以继续作为线程加入到它们的run()方法中。

如果你想学习和理解连接两个线程的概念,请在运行方法的for循环中提供Thread.sleep(1000)。