Java线程连接3

时间:2013-08-13 20:08:41

标签: java multithreading

程序创建线程t0,它产生线程t1,然后创建线程t2和t3。执行线程t3后,应用程序永远不会返回到之前生成的其他线程(t0,t1,t2)和他们被困住了。

为什么线程t0t1t2被暂停?

     public class Cult extends Thread 
            {  
                private String[] names = {"t1", "t2", "t3"};
                static int count = 0;
                public void run() 
                {
                    for(int i = 0; i < 100; i++) 
                    {
                        if(i == 5 && count < 3) 
                        {
                            Thread t = new Cult(names[count++]);
                            t.start();
                            try{
                                Thread.currentThread().join();
                            }
                            catch(InterruptedException e)
                            {
                                e.printStackTrace();
                            }
                        }
                        System.out.print(Thread.currentThread().getName() + " ");
                    } 
                 }

                 public static void main(String[] a`)
                 {
                     new Cult("t0").start();
                 }
            }

2 个答案:

答案 0 :(得分:2)

你错过的最重要的一点:

Thread.currentThread().join();

源代码中的方法join使用isAlive方法。

public final synchronized void join(long millis) 
    ...
    if (millis == 0) {
        while (isAlive()) {
        wait(0);
        }
    ...
    }

这意味着Thread.currentThread().join()仅在Thread.currentThread()失效时才会返回。

但是在你的情况下,由于Thread.currentThread()中运行的代码本身就是不可能的 这种代码的和平Thread.currentThread().join()。这就是为什么在线程3完成后你的程序应该挂起并且之后没有任何事情发生。

enter image description here

答案 1 :(得分:1)

  

为什么线程t0,t1和t2暂停?线程t3的执行完成。

t3完成,因为它尝试分叉第4个线程,因此不会尝试join()使用它自己的线程。以下行永远不会返回,所以t0,t1和t2都停在那里并永远等待:

Thread.currentThread().join();

这是要求当前线程等待本身完成哪个不起作用。我怀疑你是想说t.join();等待刚刚分叉完成的线程。

以下是关于您的代码的一些其他想法,没有明显的顺序:

  • 您应该考虑implements Runnable而不是extends Thread。见这里:"implements Runnable" vs. "extends Thread"

  • 您在多个线程中使用共享的static变量count,没有任何锁定保护。最佳解决方案是使用AtomicInteger而不是int。你可能在这里没有问题,因为每个线程都在修改count,然后分叉另一个线程但是如果你试图分叉2个线程,由于数据竞争条件,这将是一个真正的问题。

    < / LI>
  • 我不确定你为什么只生成另一个帖子if(i == 5 && count < 3)i在该循环中只有5 一次。这真的是你想要的吗?

  • 建议在 top 类中声明
  • String[] names = {"t1", "t2", "t3"};个字段。否则他们会被埋没在代码中并迷失。

  • main中,您启动Cult线程,然后主线程结束。这是不必要的,您只需在cult.run();中调用main,然后使用主线程。

  • Cult(String s) { super(s); }让构造函数调用具有相同参数的超级构造函数是没有意义的。这可以删除。

  • 这是值得商榷的,但我倾向于将main方法置于班级的顶端,而不是埋葬它,因为它是“入口”方法。构造函数也是如此。那些应该高于 run()方法。

  • catch(Exception e) {}真正的错误模式。至少你应该做e.printStackTrace();或以某种方式记录它。捕获和删除异常会隐藏很多的问题。此外,应将Exception更改为catch(InterruptedException e)。您希望限制您的catch块只是块抛出的异常,否则如果您在某处复制并粘贴该块,这可能会再次隐藏问题。

  • 这是一个很好的做法,但从不使用像3这样的常量来匹配另一个数据项。在这种情况下,最好使用names.length,这是3.这意味着如果要增加线程数,则不需要在代码中更改2个位置。您也可以将名称设为"t" + count并完全删除names数组。