A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 胡建伟 中级黑马   /  2013-11-10 20:05  /  3878 人查看  /  11 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 胡建伟 于 2013-11-13 00:15 编辑

今天复习多线程,做练习时候在网上找到一个三线程问题:有三个线程ID分别是A、B、C,请有多线编程实现,在屏幕上循环打印10次ABCABC
看似很简单,可是做起来费了很大劲,最后逛论坛找到一种使用join()方法实现,但是还是没有完全理解,希望高手们能帮忙详细解释下,除了此方法是否还有其他方法可以实现?
package itheimabiji;
public class duoxiancheng {
public static void main(String[] args) {
   Thread_E tc = new Thread_E();  
         Thread_E tb = new Thread_E();  
         Thread_A ta = new Thread_A();  
           
         ta.setThread(tb);  
         tb.setThread(tc);   
         tc.setThread(ta);
           
         ta.setName("A");  
         tb.setName("B");  
         tc.setName("C");  
           
         ta.start();  
         tb.start();  
         tc.start();  
           
     }  
}  
class Thread_A extends Thread {  
     Thread t;  
     public void setThread(Thread t) {  
         this.t = t;  
     }  
     public void run() {  
         int i = 0;  
         while(i++ < 10) {  
             System.out.print(Thread.currentThread().getName());  
             t.interrupt();  
             try {  
                 this.join();  
             } catch (InterruptedException e) {  
                  
             }         
         }  
     }  
}  
class Thread_E extends Thread {  
     Thread t;  
     public void setThread(Thread t) {  
         this.t = t;  
     }  
     public void run() {  
         int i = 0;  
         while(i++ < 10) {  
             try {  
                 this.join();  
                  
             } catch (InterruptedException e) {  
                  
             }         
             System.out.print(Thread.currentThread().getName());  
             t.interrupt();  
         }  
     }  
}

评分

参与人数 1技术分 +1 收起 理由
黄炳期 + 1

查看全部评分

11 个回复

倒序浏览
看不懂题目呢???
回复 使用道具 举报
t1,t2是两个独立的线程,还有一个线程就是我们的主线程。
        t1.start();
        t2.start();//开始执行线程
t1.join();//当前线程等待t1执行完成,注意这是指main线程会等待t1执行完成以后才执行后面的代码。这里与t2毫无关系,所以t2当然不会等待,等待的只是main线程。
class ThreadTesterA implements Runnable {

        private int counter;

        @Override
        public void run() {
                while (counter <= 10) {
                        System.out.print("Counter = " + counter + " ");
                        counter++;
                }
                System.out.println();
        }
}

class ThreadTesterB implements Runnable {

        private int i;

        @Override
        public void run() {
                while (i <= 10) {
                        System.out.print("i = " + i + " ");
                        i++;
                }
                System.out.println();
        }
}

public class ThreadTester {
        public static void main(String[] args) throws InterruptedException {
                Thread t1 = new Thread(new ThreadTesterA());
                Thread t2 = new Thread(new ThreadTesterB());
                t1.start();
                t1.join(); // wait t1 to be finished
                t2.start();
                t2.join(); // in this program, this may be removed
        }
}

评分

参与人数 1技术分 +1 收起 理由
黄炳期 + 1

查看全部评分

回复 使用道具 举报
这个程序的执行顺序是这样的,如果线程ta先运行,则打印A,然后将线程tb的中断标志设置为true,自己调用join方法进入阻塞。在这里补充一句,interrupt()并不直接中断线程,而是设定中断标识为true,抛出异常进入catch语句块后中断标识重新置为false。如果线程tb接着运行,当tb运行到this.join方法时检查中断标志,因为之前已经置为true,这里会抛出异常进入catch语句块,并将自己的中断标志置为false,然后打印B,并将tc的中断标识置为true,tb继续运行会在this.join方法这里进入阻塞和tb一样。此时ta和tb都处于阻塞状态,tc获得执行权。tc中和tb一样,只是最后打印的是C,并且将ta的中断标志置为true,因为在join方法哪里会不断的检查中断标志,所以ta会抛出异常进入catch块继续执行,打印A后又将tb的中断标志置为true,沿着之前的顺序依次执行直到所有循环结束。由tb或者tc开始也是差不多的,lz可以按 这种分析方法自己理一遍
回复 使用道具 举报
  1. class Print implements Runnable
  2. {
  3.         private String[] s={"A","B","C"};
  4.         private int i=0;
  5.         private int x=31;

  6.         public void run()
  7.         {
  8.                 while(x>0)
  9.                 {
  10.                         synchronized(obj.a)
  11.                         {
  12.                                 System.out.print(s[i]);
  13.                                 if(i<2)
  14.                                         i++;
  15.                                 else
  16.                                         i=i-2;
  17.                                 x--;
  18.                         }
  19.                 }
  20.         }
  21. }

  22. class obj
  23. {
  24.         static Object a=new Object();
  25. }

  26. class Main
  27. {
  28.         public static void main(String[] args)
  29.         {
  30.                 Print p=new Print();
  31.                 Thread A=new Thread(p);
  32.                 Thread B=new Thread(p);
  33.                 Thread C=new Thread(p);

  34.                 A.start();
  35.                 B.start();
  36.                 C.start();
  37.         }
  38. }
复制代码
不知道我这个符不符合你的题意?

评分

参与人数 1技术分 +1 收起 理由
黄炳期 + 1

查看全部评分

回复 使用道具 举报
之前的那个应该不符合题意,这个肯定符合,就是有点变态,估计比他那个还难懂。。。。
回复 使用道具 举报
之前的那个应该不符合题意,这个肯定符合,就是有点变态,估计比他那个还难懂。。。。
  1. import java.util.concurrent.locks.*;
  2. class LockTest
  3. {
  4.         private static ReentrantLock lock=new ReentrantLock();
  5.         private static Condition cd=lock.newCondition();
  6.         private static Condition cd1=lock.newCondition();
  7.         private static Condition cd2=lock.newCondition();
  8.         public static void main(String[] args)
  9.         {
  10.                 Thread td1=new A();
  11.                 Thread td2=new B();
  12.                 Thread td3=new C();
  13.                 td1.setName("A");
  14.                 td2.setName("B");
  15.                 td3.setName("C");
  16.                
  17.                 td3.start();
  18.                 Thread.yield();
  19.                 td2.start();
  20.                 Thread.yield();
  21.                 td1.start();


  22.         }

  23.         static class A extends Thread
  24.         {
  25.                 public void run()
  26.                 {
  27.                         int x=0;
  28.                         while(x<10)
  29.                         {
  30.                        
  31.                         lock.lock();
  32.                         try
  33.                         {
  34.                                 if(x!=0)
  35.                                 {
  36.                                         cd.await();               
  37.                                 }
  38.        
  39.                         }
  40.                         catch (Exception e)
  41.                         {
  42.                         }

  43.                         System.out.print(Thread.currentThread().getName());
  44.                         cd1.signal();
  45.                         x++;
  46.                         lock.unlock();

  47.                         }
  48.                 }
  49.         }

  50.         static class B extends Thread
  51.         {
  52.                 public void run()
  53.                 {
  54.                         int x=0;
  55.                         while(x++<10)
  56.                         {
  57.                         lock.lock();
  58.                         try
  59.                         {
  60.                                 cd1.await();
  61.                         }
  62.                         catch (Exception e)
  63.                         {
  64.                         }
  65.                         System.out.print(Thread.currentThread().getName());
  66.                         cd2.signal();
  67.                         lock.unlock();
  68.                         }
  69.                 }
  70.         }

  71.         static class C extends Thread
  72.         {
  73.                 public void run()
  74.                 {       
  75.                         int x=0;
  76.                         while(x++<10)
  77.                         {
  78.                         lock.lock();
  79.                         try
  80.                         {
  81.                                 cd2.await();
  82.                         }
  83.                         catch (Exception e)
  84.                         {
  85.                         }

  86.                         System.out.print(Thread.currentThread().getName());
  87.                         cd.signal();
  88.                         lock.unlock();
  89.                         }

  90.                 }
  91.         }


  92. }


复制代码
回复 使用道具 举报
刚刚做了下测试,你你贴出来的那个代码有陷入全部等待的状态,只是计算机执行速度特别快,所以发生的概率微乎其微,你在ta.start()方法后面加一个sleep(100),效果一下就出来了,如下图
  1.          ta.start();
  2.                  try
  3.                  {
  4.                          Thread.sleep(100);
  5.                  }
  6.                  catch (Exception e)
  7.                  {
  8.                  }
  9.                  System.out.println("over");
  10.          tb.start();  
  11.          tc.start();  
复制代码
正确的写法应该是:
  1.          tb.start();  
  2.          tc.start();  
  3.                  try
  4.                  {
  5.                          Thread.sleep(100);
  6.                  }
  7.                  catch (Exception e)
  8.                  {
  9.                  }
  10.                  ta.start();
复制代码
时间可以再小一些,或者直接用yield()来代替应该也可以,不过时间越短,越有可能进入全部等待状态。
回复 使用道具 举报
至于你没理解那个代码,我觉得理解这两个方法的用法应该就能理解了:
1.this.join():意思是当前线程进入等待状态。一般是A线程启动后,在A线程的线程内启动了B线程,这时B.join()就代表着A等着B结束,但是此时不代表着C、D、E、等等的线程也等着B结束。而在他这里比较特殊,本身等待本身结束,就代表着进入了死循环,或者就是等待的状态。
2.t.interrupt():意思是接触t的冻结状态。比如调用过this.join方法的这样的线程,使用该方法后,就会解除无限等待状态,拥有执行资格。
回复 使用道具 举报
@黄炳期 这个问题我回答的这么详细,怎么不给我分啊
回复 使用道具 举报
spiderman 发表于 2013-11-16 19:23
@黄炳期 这个问题我回答的这么详细,怎么不给我分啊

提问结束的帖子不要再回答问题,不是说回答了就能得分的。你这隔了两天才回答问题
回复 使用道具 举报
黄炳期 发表于 2013-11-16 21:49
提问结束的帖子不要再回答问题,不是说回答了就能得分的。你这隔了两天才回答问题 ...

噢。。这样。。。没留意。。。咳,白写了那么多。谢谢了哈
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马