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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 张向辉 于 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, 下载次数: 59)

thread.jpg

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1 赞一个!

查看全部评分

16 个回复

倒序浏览

RE: 关于 Runnable 实现多线程的问题...实在整不到什么了..求...

你使用了同步,去掉synchronized就可以实现多线程

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

122.png

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1 赞一个!

查看全部评分

回复 使用道具 举报
梁俊 发表于 2013-1-17 23:15
你使用了同步,去掉synchronized就可以实现多线程

如果我加上 try{Thread.sleep(10);}catch (Exception e){} 就挂了
回复 使用道具 举报
你想让两个线程争抢线程,那为什么要同步呢,这样好像不能同步吧,我感觉
回复 使用道具 举报
梁俊 发表于 2013-1-17 23:30
你想让两个线程争抢线程,那为什么要同步呢,这样好像不能同步吧,我感觉 ...

不用同步会出意外的.........所以我也郁闷..
回复 使用道具 举报
不应该把synchronized 方法run方法上,应该用同步代码块
回复 使用道具 举报
txl 中级黑马 2013-1-17 23:47:55
7#
我试了下,加上那个当然挂,不会输出任何数据,因为
while(x>0)       //x永远等于零,不会执行下面的代码

//try{Thread.sleep(10);}catch (Exception e){}        

所以线程会一直sleep下去
回复 使用道具 举报
本帖最后由 黄金龙 于 2013-1-18 00:22 编辑
黑马唐贤来 发表于 2013-1-17 23:47
我试了下,加上那个当然挂,不会输出任何数据,因为
while(x>0)       //x永远等于零,不会执行下面的代码


不是10毫秒后就执行下面的代码吗?加了锁其他的线程应该进不来才对的啊
回复 使用道具 举报
黄锦成 发表于 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 00:20
不是10毫秒后就执行下面的代码吗?加了锁其他的线程应该进不来才对的啊

你的while加在try{}catch(){}上面了 所以x根本没有被执行x--
所以一直while下去啊
你应该吧syso一起加在while里面吧
回复 使用道具 举报
首先给你回复下关于同步代码和同步函数的问题,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. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1 赞一个!

查看全部评分

回复 使用道具 举报
txl 中级黑马 2013-1-18 11:30:25
12#
黄金龙 发表于 2013-1-18 00:20
不是10毫秒后就执行下面的代码吗?加了锁其他的线程应该进不来才对的啊

看错了,是x永远等于100,一直会循环判断下去
回复 使用道具 举报
sleep();释放资源不释放锁,你可以改用wait();试试,但是在执行结束后记得要调用notify();把另一线程唤醒
回复 使用道具 举报
对于加上 try{Thread.sleep(10);}catch (Exception e){} 就挂了的原因是:此线程sleep时,主线程已经执行结束了,所以程序不动了。要想这个线程休息后还能打印,得保证主线程在其休息结束后还存活。可以在主函数里加个while(true){}死循环,让主线程永久存活便Ok , 可以试下看。
这个问题老毕在基础视频第12天07中有讲到
回复 使用道具 举报
注意同步修饰符不能再run上使用那样会出事的,同步代码块是加载操作数据的代码上的不是加载run方法上的,run方法里写的要线程执行的任务,如果你加载while循环上,也是不行的,试想一下,一个线程进入时,他会循环完,跳出代码块的范围,另一个线程才能够进入,那定义的线程将毫无意义。
回复 使用道具 举报
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-18 00:27
我已经测试了..就算加在也是不行

这个关系到你是加到循环外还是循环外,我建议加在循环内,while使用true,在循环里使用if来判断是否大于0
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马