黑马程序员技术交流社区

标题: 线程问题 [打印本页]

作者: 睡不够的猪    时间: 2013-10-23 11:54
标题: 线程问题
  1. class SaleTicketTest
  2. {
  3. public static void main(String[] args)
  4. {
  5. SaleTicket t =new SaleTicket();
  6. new Thread(t).start();
  7. new Thread(t).start();
  8. new Thread(t).start();
  9. new Thread(t).start();
  10. }
  11. }


  12. class SaleTicket implements Runnable
  13. {
  14. private int ticket=100;

  15. public void run()
  16. {

  17. while(ticket>0)
  18. {
  19. /*
  20. 假如线程0、1、2、3都进来了
  21. 然后0线程执行了 然后1、2、3都执行
  22. 结果会出现负数 说明1、2、3执行后打印的ticket是ticket--之后的数据

  23. 那为什么会出现小数据打印后还会打印大数据的现象呢???

  24. ----->比如 0线程打印了63 出现1线程打印64是什么原因?
  25. */
  26. try
  27. {
  28. Thread.sleep(10);
  29. }
  30. catch (Exception e)
  31. {
  32. }
  33. System.out.println(Thread.currentThread().getName()+"run...:"+ticket--);


  34. }

  35. }
  36. }
复制代码


作者: 周学彬    时间: 2013-10-23 12:11
本帖最后由 周学彬 于 2013-10-23 12:13 编辑

由于是多线程并发执行,所以每个线程会抢占所有的系统资源,包括输出设备——控制台。所以,当某个线程执行了run()方法,即将打印时,却被另一个线程抢先执行run()方法,并抢占了输出控制台资源,那么就会执行后一个线程,即打印较小的票了。
至于为什么打印负数,那时因为该段代码的多线程实现并不安全,因为操作共享数据而没有同步锁,你看到后面的视频就会明白了。最简单的办法就是给run()方法添加一个同步声明,使用synchronized语句,这样就不会打印负数了
代码实现如下:
  1. class ThreadTest
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 SaleTicket t =new SaleTicket();
  6.                 new Thread(t).start();
  7.                 new Thread(t).start();
  8.                 new Thread(t).start();
  9.                 new Thread(t).start();
  10.         }
  11. }


  12. class SaleTicket implements Runnable
  13. {
  14.         private int ticket=100;
  15.         
  16.         public void run()
  17.         {
  18.                 synchronized(this) {
  19.                 while(ticket>0)
  20.                 {
  21.                         /*
  22.                         假如线程0、1、2、3都进来了
  23.                         然后0线程执行了 然后1、2、3都执行
  24.                         结果会出现负数 说明1、2、3执行后打印的ticket是ticket--之后的数据
  25.                         
  26.                         那为什么会出现小数据打印后还会打印大数据的现象呢???
  27.                         
  28.                         ----->比如 0线程打印了63 出现1线程打印64是什么原因?
  29.                         */
  30.                         
  31.                         try
  32.                         {
  33.                                 Thread.sleep(10);
  34.                         }
  35.                         catch (Exception e) {}
  36.                                 System.out.println(Thread.currentThread().getName()+"run...:"+ticket--);
  37.                         }
  38.                 }
  39.         
  40.         }
  41. }
复制代码

作者: 睡不够的猪    时间: 2013-10-23 12:34
周学彬 发表于 2013-10-23 12:11
由于是多线程并发执行,所以每个线程会抢占所有的系统资源,包括输出设备——控制台。所以,当某个线程执行 ...

我知道是线程抢夺cpu执行权的问题 按照你说的 会出现多个线程卖出同一个票号的现象 但是还是想不明白为什么会先出现小号 再出现大号的现象

另外你把锁加在循环外面的话 结果是某一个线程会把票都卖完的!
作者: 乔兵    时间: 2013-10-25 08:09
楼主你好,如果问题已解决请将帖子状态修改为提问结束,

如果未解决请继续提问,谢谢合作

修改方法请看解释帖:http://bbs.itheima.com/thread-89313-1-1.html




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