黑马程序员技术交流社区

标题: 关于 Runnable 实现多线程的问题...实在整不到什么了..求解.. [打印本页]

作者: 黄金龙    时间: 2013-1-17 22:57
标题: 关于 Runnable 实现多线程的问题...实在整不到什么了..求解..
本帖最后由 张向辉 于 2013-1-19 12:42 编辑
  1. class Demo11
  2. {
  3. public static void main(String[] args)
  4. {
  5. Demo d = new Demo();
  6. Thread t1 = new Thread(d);
  7. Thread t2 = new Thread(d);
  8. t1.start();
  9. t2.start();
  10. }
  11. }

  12. class Demo implements Runnable
  13. {
  14. private int x = 100;

  15. public synchronized void run()
  16. {
  17. while(x>0)
  18. //try{Thread.sleep(10);}catch (Exception e){}
  19. System.out.println(Thread.currentThread().getName()+"-----"+x--);
  20. }

  21. }

  22. //不知道出错在什么地方..求解.....
  23. //加上这个就挂了....为什么..... try{Thread.sleep(10);}catch (Exception e){}
  24. //这里加锁了..就算sleep了..时间到了..也应该继续执行后面的代码的..
复制代码

thread.jpg (23.39 KB, 下载次数: 101)

thread.jpg

作者: 梁俊    时间: 2013-1-17 23:15
标题: RE: 关于 Runnable 实现多线程的问题...实在整不到什么了..求...
你使用了同步,去掉synchronized就可以实现多线程

122.png (8.37 KB, 下载次数: 101)

122.png

作者: 黄金龙    时间: 2013-1-17 23:26
梁俊 发表于 2013-1-17 23:15
你使用了同步,去掉synchronized就可以实现多线程

如果我加上 try{Thread.sleep(10);}catch (Exception e){} 就挂了
作者: 梁俊    时间: 2013-1-17 23:30
你想让两个线程争抢线程,那为什么要同步呢,这样好像不能同步吧,我感觉
作者: 黄金龙    时间: 2013-1-17 23:40
梁俊 发表于 2013-1-17 23:30
你想让两个线程争抢线程,那为什么要同步呢,这样好像不能同步吧,我感觉 ...

不用同步会出意外的.........所以我也郁闷..
作者: 黄锦成    时间: 2013-1-17 23:41
不应该把synchronized 方法run方法上,应该用同步代码块
作者: 黄金龙    时间: 2013-1-18 00:20
本帖最后由 黄金龙 于 2013-1-18 00:22 编辑
黑马唐贤来 发表于 2013-1-17 23:47
我试了下,加上那个当然挂,不会输出任何数据,因为
while(x>0)       //x永远等于零,不会执行下面的代码


不是10毫秒后就执行下面的代码吗?加了锁其他的线程应该进不来才对的啊
作者: 黄金龙    时间: 2013-1-18 00:27
黄锦成 发表于 2013-1-17 23:41
不应该把synchronized 方法run方法上,应该用同步代码块

我已经测试了..就算加在
  1. synchronized(obj)
  2.                         {
  3.                                 while(x>0)
  4.                                 //try{Thread.sleep(10);}catch (Exception e){}
  5.                                 System.out.println(Thread.currentThread().getName()+"-----"+x--);               
  6.                         }
复制代码
也是不行
作者: 肖亚光    时间: 2013-1-18 09:07
黄金龙 发表于 2013-1-18 00:20
不是10毫秒后就执行下面的代码吗?加了锁其他的线程应该进不来才对的啊

你的while加在try{}catch(){}上面了 所以x根本没有被执行x--
所以一直while下去啊
你应该吧syso一起加在while里面吧
作者: cyh8807    时间: 2013-1-18 11:20
首先给你回复下关于同步代码和同步函数的问题,synchronized这个锁的机制想必你是了解的,线程一启动最先调用的就是run()方法,但是你将void run()方法定义为同步函数后,就只能等某一个进程运行完毕后,其他进程才可以
依次调用run()方法,所以你上面的那段代码是无法实现多线程运行的,当然你将synchronized去掉后是可以实现多线程同步的,但此时又会出现安全问题,所以需要使用synchronized同步代码块,但是这样同样你的两个线程不会开启
因为同步代码块和同步函数的作用一样,都是一个线程进来之后就阻止其后面的线程进来执行相同的数据。
其次,关于你写的代码,我猜你是想让两个线程同时打印这100个数字,同时还不出现安全问题,不知道我理解的对不??下面是我给出的一个解决办法,仅供参考
  1. class Demo11
  2. {
  3.        
  4.         public static void main(String[] args)
  5.         {
  6.                 Demo d = new Demo();
  7.                 Thread t1 = new Thread(d);
  8.                 Thread t2 = new Thread(d);
  9.                 t1.start();
  10.                 try
  11.                 {
  12.                         Thread.sleep(60);
  13.                 }catch(Exception e)
  14.                 {
  15.                         e.printStackTrace();
  16.                 }
  17.                 d.flag = false;
  18.                 t2.start();
  19.         }
  20. }

  21. class Demo implements Runnable
  22. {
  23.         private int x = 100;
  24.         public boolean flag = true;
  25.        
  26.         public  void run()
  27.         {
  28.                 if(flag)
  29.                 {
  30.                         while(true)
  31.                         {
  32.                                 synchronized(Demo.class)
  33.                                 {
  34.                                         if(x > 0)
  35.                                         {
  36.                                                 try
  37.                                                 {
  38.                                                         Thread.sleep(60);
  39.                                                 }catch(Exception e)
  40.                                                 {
  41.                                                         e.printStackTrace();
  42.                                                 }
  43.                                                 System.out.println(Thread.currentThread().getName() +"```" + x--);
  44.                                         }
  45.                                 }
  46.                         }
  47.                 }
  48.                 else
  49.                 {
  50.                         while(true)
  51.                         {
  52.                                 print();
  53.                         }
  54.                 }
  55.                        
  56.         }
  57.         public synchronized  void print()
  58.         {
  59.                 while(x>0)
  60.                         {
  61.                                 try{Thread.sleep(10);}catch (Exception e){}
  62.                                 System.out.println(Thread.currentThread().getName()+"-----"+x--);
  63.                         }
  64.         }
  65. }
复制代码

作者: 刘军亭    时间: 2013-1-18 11:46
sleep();释放资源不释放锁,你可以改用wait();试试,但是在执行结束后记得要调用notify();把另一线程唤醒
作者: Rancho_Gump    时间: 2013-1-18 13:03
对于加上 try{Thread.sleep(10);}catch (Exception e){} 就挂了的原因是:此线程sleep时,主线程已经执行结束了,所以程序不动了。要想这个线程休息后还能打印,得保证主线程在其休息结束后还存活。可以在主函数里加个while(true){}死循环,让主线程永久存活便Ok , 可以试下看。
这个问题老毕在基础视频第12天07中有讲到
作者: 高浩    时间: 2013-1-18 13:20
注意同步修饰符不能再run上使用那样会出事的,同步代码块是加载操作数据的代码上的不是加载run方法上的,run方法里写的要线程执行的任务,如果你加载while循环上,也是不行的,试想一下,一个线程进入时,他会循环完,跳出代码块的范围,另一个线程才能够进入,那定义的线程将毫无意义。
作者: 谢毅    时间: 2013-1-18 14:03
while(x>0)这是什么意思?这表示某一个线程进去了就会不断重复判断并执行,并且后续代码你是让线程sleep这是冻结状态,由于同步锁的原因其他线程又进不来所以全是一个线程打印100次。一般在同步里用while(共享数据)是拿来做生产者消费者模式的,并且使用阻塞状态wait,这样就可以唤醒其他线程,你要么改成
while (true) {
                        synchronized (this) {
                                if (x> 0) {
                                        try{Thread.sleep(10);}catch (Exception e){}
                                        System.out.println(Thread.currentThread().getName()+"-----"+x--);
                                }
                        }
                }
作者: 黄锦成    时间: 2013-1-19 16:15
黄金龙 发表于 2013-1-18 00:27
我已经测试了..就算加在也是不行

这个关系到你是加到循环外还是循环外,我建议加在循环内,while使用true,在循环里使用if来判断是否大于0




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