黑马程序员技术交流社区

标题: 多线程通信的一个问题? [打印本页]

作者: 铿锵科技    时间: 2013-2-3 17:28
标题: 多线程通信的一个问题?
本帖最后由 铿锵科技 于 2013-2-4 19:44 编辑

输出1到10的整数
有2个函数,一个输出奇数,一个输出偶数
        public static int printOdd(int i) {
                if (i % 2 == 1) {
                        System.out.println(i);
                        return ++i;
                }
                return i;
        }

        public static int printEven(int i) {
                if (i % 2 == 0) {
                        System.out.println(i);
                        return ++i;
                }
                return i;
        }
用一个线程调用输出奇数的函数,输出后等待另一线程调用输出偶数函数,循环直到10完成,2个线程结束.如何实现?想了半天想不出来,请指教!
用2个线程调用以上的函数。线程要通信,输出结要为:1 2 3 4 5 6 7 8 9 10然后2个线程结束


作者: 陈科宇    时间: 2013-2-3 18:49
public class ThreadTest {
        private  boolean flag;//判断一个线程是否执行完成
    /**
     * 输出奇数
     */
    public synchronized void printOdd()
    {
            System.out.println("开始输出奇数");

     for(int i=1;i<=10;i++)
     {
             if(i%2==1)
             {
                     System.out.print(i+"\t");
             }
             
     }
     System.out.println("\n"+"输出奇数结束");
         flag=true;
         notifyAll();
    }
    /**
     * 输出偶数
     */
    public synchronized   void printEven()
    {
            //如果奇数没有输出完成,输出偶数的线程必须等待
            if(!flag)
            {
                    try {
                                wait();
                        } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        }
            }
            else{
                    System.out.println("开始输出偶数");
                    for(int i=1;i<=10;i++)
            {
                    if(i%2==0)
                    {
                            System.out.print(i+"\t");
                    }
            }       
                    System.out.println("\n"+"输出偶数结束");

            }
           
    }
  public static void main(String[] args)
  {
          final ThreadTest tt=new ThreadTest();
          new Thread(new Runnable() {
               
                @Override
                public void run() {
                        // TODO Auto-generated method stub
                        tt.printOdd();
                }
        }).start();
          new Thread(new Runnable() {
               
                @Override
                public void run() {
                        // TODO Auto-generated method stub
                        tt.printEven();
                }
        }).start();
  }
}

作者: 陈科宇    时间: 2013-2-3 18:50
开始输出奇数
1        3        5        7        9       
输出奇数结束
开始输出偶数
2        4        6        8        10       
输出偶数结束
作者: 李挺    时间: 2013-2-3 19:31
  1. class Shu
  2. {
  3.         int i=10;  //把十共有出来
  4. }
  5. class Shuchu implements Runnable
  6. {
  7.         private Shu s;
  8.         Shuchu(Shu s) //导入1十
  9.         {
  10.                 this.s=s;
  11.         }
  12.         public void run()
  13.         {
  14.                 while (s.i>0)
  15.                 {
  16.                         synchronized(s)  //同步
  17.                         {
  18.                                 System.out.println(Thread.currentThread().getName()+"----"+s.i--);
  19.                                 s.notify();  //唤醒别人
  20.                                 try{s.wait();}catch(Exception e){}//冻结自己
  21.                                 if (s.i<=0) s.notifyAll(); //循环结束后,唤醒冻结的进程以中止进程
  22.                         }
  23.                 }
  24.                
  25.         }
  26. }

  27. class  Demo09
  28. {
  29.         public static void main(String[] args)
  30.         {
  31.                 Shu s=new Shu();
  32.                 Shuchu j=new Shuchu(s);
  33.                 Shuchu o=new Shuchu(s);
  34.                 Thread t1=new Thread(j);
  35.                 Thread t2=new Thread(o);
  36.                 t1.start();
  37.                 t2.start();
  38.         }
  39. }
复制代码
结果是
Thread-0----10
Thread-1----9
Thread-0----8
Thread-1----7
Thread-0----6
Thread-1----5
Thread-0----4
Thread-1----3
Thread-0----2
Thread-1----1
应该是你要的吧
作者: 铿锵科技    时间: 2013-2-3 19:58
以上都不是我想要的,谢了
作者: 铿锵科技    时间: 2013-2-4 13:20
陈科宇 发表于 2013-2-3 18:49
public class ThreadTest {
        private  boolean flag;//判断一个线程是否执行完成
    /**

你是2个线程一个输出奇数一个输出偶数,但2个线程没有通信,我是想2个线程通信输出为:1 2 3 4 5 6 7 8 9 10
作者: 铿锵科技    时间: 2013-2-4 13:22
李挺 发表于 2013-2-3 19:31
结果是
Thread-0----10
Thread-1----9

你是多线程调用同一函数输出

输出1到10的整数
有2个函数,一个输出奇数,一个输出偶数
        public static int printOdd(int i) {
                if (i % 2 == 1) {
                        System.out.println(i);
                        return ++i;
                }
                return i;
        }

        public static int printEven(int i) {
                if (i % 2 == 0) {
                        System.out.println(i);
                        return ++i;
                }
                return i;
        }
用一个线程调用输出奇数的函数,输出后等待另一线程调用输出偶数函数,循环直到10完成,2个线程结束.如何实现?想了半天想不出来,请指教!
用2个线程调用以上的函数。线程要通信,输出结要为:1 2 3 4 5 6 7 8 9 10然后2个线程结束
作者: 陈科宇    时间: 2013-2-4 14:18
不要意思,我没有看清楚你的要求,其实道理是一样的。两个线程控制一个变量递减,我就不贴出代码了。
作者: 黄鸿达    时间: 2013-2-4 16:42
本帖最后由 黄鸿达 于 2013-2-4 16:52 编辑
  1. import java.util.concurrent.locks.*;


  2. public class Th {
  3. static void show(Object obj){
  4. System.out.println("你要的数:-------------------------"+obj);
  5. }
  6. public static void main(String[] args) {
  7. 奇数 j=new 奇数();
  8. 偶数 o=new 偶数();
  9. Thread t1=new Thread(j);
  10. Thread t2=new Thread(o);
  11. t1.start();
  12. // try {Thread.sleep(100);} catch (InterruptedException e) {}
  13. t2.start();
  14. }

  15. }
  16. class Data{
  17. public static int num=1;
  18. Data(){
  19. }

  20. }
  21. class Lock{
  22. static ReentrantLock lock=new ReentrantLock();
  23. static Condition 偶数监视=lock.newCondition();
  24. static Condition 奇数监视=lock.newCondition();
  25. }
  26. class 奇数 implements Runnable{
  27. private Data d;
  28. public static int printOdd(int i) {
  29. // System.out.println(Thread.currentThread()+"~~~从线程1传入"+i+"~~~");
  30. // System.out.println("此时num的数值为"+i);
  31. if (i % 2 == 1) {
  32. Th.show(i);
  33. // System.out.println(Thread.currentThread()+"---第"+i+"次---");
  34. // System.out.println(Thread.currentThread()+"---将从线程0传出"+(i+1)+"---");
  35. return ++i;
  36. }
  37. return i;
  38. }
  39. public void run(){
  40. while(Data.num!=11)
  41. {
  42. Data.num=printOdd(Data.num);
  43. try {
  44. Lock.lock.lock();
  45. // System.out.println("线程1获取锁定\n");
  46. Lock.偶数监视.signal();
  47. // System.out.println("将对线程2叫醒\n");
  48. Lock.奇数监视.await();
  49. // System.out.println("线程1要sleep\n"+Data.num);
  50. if(Data.num==11){
  51. Lock.偶数监视.signal();}

  52. } catch (InterruptedException e) {
  53. }
  54. finally{
  55. Lock.lock.unlock();
  56. // System.out.println("线程1解锁 线程2\n"+Data.num);
  57. }
  58. }
  59. }
  60. }
  61. class 偶数 implements Runnable{
  62. public static int printEven(int i) {
  63. // System.out.println(Thread.currentThread()+"~~~从线程0传入"+i+"~~~");
  64. // System.out.println("此时num的数值为"+i);
  65. if (i % 2 == 0) {
  66. Th.show(i);
  67. // System.out.println(Thread.currentThread()+"---第"+i+"次---");
  68. // System.out.println(Thread.currentThread()+"---将从线程1传出"+(i+1)+"---");
  69. return ++i;
  70. }
  71. return i;
  72. }
  73. public void run(){
  74. while(Data.num!=11)
  75. {
  76. Data.num=printEven(Data.num);
  77. try {
  78. Lock.lock.lock();
  79. // System.out.println("线程2获取锁定\n");
  80. Lock.奇数监视.signal();
  81. // System.out.println("将对线程1叫醒\n");
  82. Lock.偶数监视.await();
  83. // System.out.println("线程2要sleep\n"+Data.num);
  84. if(Data.num==11){
  85. Lock.奇数监视.signal();}

  86. } catch (InterruptedException e) {
  87. }
  88. finally{
  89. Lock.lock.unlock();
  90. // System.out.println("线程2解锁 线程1\n"+Data.num);
  91. }
  92. }
  93. }
  94. }
复制代码
你看这样满意不?我是以你给的函数为基础 ,加代码的。2个线程各自调用你所给个不同函数。那些中文字对象,我是省得弄混,才写中文,调试如果不能识别中文自己改。

遇到的问题1:一开始写没加while循环 导致每个奇数 偶数 只算一次没了
后来再主程序+了while循环把t1.start t2.start括起来,发生IllegalThreadStateException,原来是我多次调用start方法了

遇到的问题2:后来在个线程run里面加上while后,数据错乱
然后加入了锁,但是之后出现IllegalMonitorStateException

遇到的问题3:后来baidu,原来监视器都是都是同一个,接着NEW 了2个Condition监视器后,可以了。但是算出10后,程序没停掉,找了半天不知道怎么回事。
后来才知道是线程2在睡觉,因为数已经到10 不循环,所以也没人叫醒线程2,后来加个if语句判断是否到11,到了就叫醒。


作者: 铿锵科技    时间: 2013-2-4 18:53
黄鸿达 发表于 2013-2-4 16:42
你看这样满意不?我是以你给的函数为基础 ,加代码的。2个线程各自调用你所给个不同函数。那些中文字对象, ...

哦,谢了,我也好了




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2