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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 爪哇攻城狮 中级黑马   /  2013-4-11 14:09  /  2097 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 李松柏 于 2013-4-11 16:35 编辑
  1. class ThreadDemo1
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 TestThread tt = new TestThread();
  6.                 tt.start();
  7.                 tt.start();
  8.                 tt.start();
  9.                 tt.start();
  10.         }
  11. }

  12. class TestThread extends Thread
  13. {
  14.         int tickets = 100;
  15.         public void run()
  16.         {
  17.                 while(true)
  18.                 {
  19.                         if(tickets>0)
  20.                         System.out.println(Thread.currentThread().getName()+" is saling ticket "+tickets--);
  21.                 }
  22.         }
  23. }
复制代码
(代码1)
运行结果:
  1. class ThreadDemo1
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 TestThread tt = new TestThread();
  6.                 new Thread(tt).start();
  7.                 new Thread(tt).start();
  8.                 new Thread(tt).start();
  9.                 new Thread(tt).start();
  10.         }
  11. }

  12. class TestThread implements Runnable
  13. {
  14.         int tickets = 100;
  15.         public void run()
  16.         {
  17.                 while(true)
  18.                 {
  19.                         if(tickets>0)
  20.                         System.out.println(Thread.currentThread().getName()+" is saling ticket "+tickets--);
  21.                 }
  22.         }
  23. }
复制代码
(代码2)

-------------------------------------------------------------
代码1运行出错(如上图)。代码2运行正常!!!
求解??

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

6 个回复

倒序浏览
你就这样什么都不做就运行了啊,看完多线程,上了锁就好了

点评

汗- - ! 上锁同步,我知道。我是问代码1运行出错的原因。为什么代码2运行就正常呢?  发表于 2013-4-11 14:26
回复 使用道具 举报
  1. /**
  2. 1,定义类实现Runnable接口
  3. 2,覆盖Runnable接口中的run方法(将线程要运行的代码存放在该run方法中)
  4. 3,通过Thread类建立线程对象
  5. 4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数(因为自定义的run方法所属的对象是Runnable接口的子类对象,所以要让线程去指定对象的run方法)
  6. 5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法

  7. 卖票程序:多个窗口买票
  8. */
  9. class Ticket implements Runnable//实现Runnable接口
  10. {
  11.         private int tick = 10000;
  12.         Object obj = new Object();
  13.         public void run()//将线程要运行的代码存放在该run方法中
  14.         {
  15.                 while(true)
  16.                 {        //多线程执行共享数据的语句

  17.                         synchronized(obj)//同步代码块
  18.                         {
  19.                                 if(tick>0)
  20.                                 {        //由于临时状态,阻塞,多线程可能出现安全隐患

  21.                                         System.out.println(Thread.currentThread().getName()+"..."+ tick--);
  22.                                 }
  23.                         }
  24.                 }
  25.         }
  26. }

  27. class TicketDemo
  28. {
  29.         public static void main(String[] args)
  30.         {
  31.                 Ticket t = new Ticket();//建立Runnable接口的子类对象
  32.                 Thread t1 = new Thread(t);//Thread类建立线程对象,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
  33.                 Thread t2 = new Thread(t);
  34.                 Thread t3 = new Thread(t);       
  35.                 t1.start();//调用Thread类的start方法开启线程并调用Runnable接口子类的run方法
  36.                 t2.start();
  37.                 t3.start();       
  38.         }
  39. }
复制代码

点评

Thinks  发表于 2013-4-11 14:35

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 熊永标 于 2013-4-11 14:24 编辑

继承至thread类所创建的线程不能多次启动,
TestThread tt = new TestThread();

                tt.start();

                tt.start();

                tt.start();

                tt.start();
同是一个线程对象,你启动了四次,当然会报IIIegalThreadStateException异常了,而第二个能正常,是因为每次都会先new一个线程对象出来,然后再启动,每个对象只启动一次,所以运行正常
TestThread tt = new TestThread();

                new Thread(tt).start();

                new Thread(tt).start();

                new Thread(tt).start();

                new Thread(tt).start();
tt实现了Runnable接口,所以把Thread传递到Thread的构造函数,是可以接受的,这样在每次启动线程时,就不会出错了.

点评

嗯嗯,谢谢解答!但是我看了张孝祥老师的线程那一课的视频中,也是代码1,他运行就没出错。无语了!  发表于 2013-4-11 14:34

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
你看抛出的异常呀,是一个"IllegalThreadStateException",说明你一个Thread对象重复调用了多次start()方法
你看在这里
  1. class ThreadDemo1

  2. {

  3.         public static void main(String[] args)

  4.         {

  5.                 TestThread tt = new TestThread();  //只实例化了一个对象

  6.                 tt.start();         //下边多次调用start方法,就会抛出IllegalThreadStateException异常

  7.                 tt.start();

  8.                 tt.start();

  9.                 tt.start();

  10.         }

  11. }

复制代码
而下边这段是这样
  1. class ThreadDemo1

  2. {

  3.         public static void main(String[] args)

  4.         {

  5.                 TestThread tt = new TestThread();

  6.                 new Thread(tt).start();         //下面这几个start()方法每一个都是一个新实例化的匿名对象调用的,是不同的对象,自然就不会抛出上述的异常

  7.                 new Thread(tt).start();

  8.                 new Thread(tt).start();

  9.                 new Thread(tt).start();

  10.         }

  11. }

复制代码

点评

额,谢谢哈!  发表于 2013-4-11 14:35

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
多线程的问题一般都会出现异常,你要cry...catch 捕获  或throw抛出
回复 使用道具 举报
问题解决了就改成已解决
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马