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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

    看视频和上网都了解了继承Thread类以后,资源是不可共享的,但是看我的代码
  1. class MyThread extends Thread
  2. {
  3.         private int ticket = 5;
  4.         public void run()
  5.         {
  6.                 while(ticket > 0)
  7.                 {
  8.                         System.out.println(Thread.currentThread().getName()+"--->"+this.ticket--);
  9.                 }
  10.         }
  11. }
  12. public class ThreadDemo
  13. {
  14.         public static void main(String[] args)
  15.         {
  16.                 MyThread mt = new MyThread();
  17.                 new Thread(mt).start();          //是不是这里有问题?怎么看怎么不对,又想不通
  18.                 new Thread(mt).start();
  19.         }
  20. }
复制代码
输出结果:
Thread-1--->5
Thread-2--->4
Thread-1--->3
Thread-2--->2
Thread-1--->1
这不是说明ticket资源被共享了吗?这是怎么回事?怎么改?如果要实现共享,又该如何实现?

评分

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

查看全部评分

4 个回复

倒序浏览
本帖最后由 李阳 于 2013-3-12 02:38 编辑
  1. class MyThread extends Thread
  2.         private int ticket = 5;
  3.         public void run()
  4.         {
  5.                 while(ticket > 0)
  6.                 {
  7.                         System.out.println(Thread.currentThread().getName()+"--->"+this.ticket--);
  8.                 }
  9.         }
  10. }
  11. class ThreadDemo
  12. {
  13.         public static void main(String[] args)
  14.         {
  15.                 MyThread mt = new MyThread();
  16.                 MyThread mt1 = new MyThread();
  17.                 mt.start();//线程开启方式1,不共享资源。
  18.                 mt1.start();
  19.                  //因为Thread是实现runnable接口而来的,所以MyThresd继承了Thread后也可以方式2开启线程。
  20.                 //new Thread(mt).start(); //线程开启方式2,和实现Runnable没啥区别。共享线程资源。  
  21.                 //new Thread(mt).start();
  22.                         
  23.         }
  24. }
  25. /*
  26. 开启方式1没有共享资源,因为线程的资源是不同的对象
  27. 开启方式2共享了资源,因为线程执行的内容都来自同一个对象所以资源共享了。
  28. 常规做法是不想让多线程共享资源就继承Thread类。让多线程共享资源就实现接口Runnable。你的那种做法我是第一次见,估计很少这样做吧。
  29. 继承方式和实现方式的区别:
  30.     1.继承方式只能继承一个类,而实现方式可以继承一个类同时实现多个接口。避免了单继承的局限性。
  31.     2.线程代码存放位置不一样。继承Thread线程代码存放在Thread子类的run方法中(覆盖)。实现runnable的线程代码存放在接口子类的run方法中(实现)。
  32.     3.继承方式只能实现一个线程对一个线程资源的操作,而实现方式还能够实现多个线程对一个线程资源的操作。
  33. */
复制代码
回复 使用道具 举报
使用接口 加静态代码块解决
class Ticket implements Runnable
{
        private  int tick = 50;
        Object obj = new Object();
        public void run()
        {
                while(true)
                {
                        synchronized(obj)
                        {
                                if(tick>0)
                                {
                                        System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);
                                }
                        }
                }
        }
}


class  TicketDemo2
{
        public static void main(String[] args)
        {

                Ticket t = new Ticket();

                Thread t1 = new Thread(t);
                Thread t2 = new Thread(t);
                Thread t3 = new Thread(t);
                Thread t4 = new Thread(t);
                t1.start();
                t2.start();
                t3.start();
                t4.start();
        }
}
回复 使用道具 举报
本帖最后由 李辉 于 2013-3-12 04:24 编辑

问题的本质是:
    1.你这个MyThread虽然继承了Thread,但是你没用用它来创建线程,你虽然用它创建了一个mt,但mt并没有开启,只是用作参数。
    2.你这个程序本质上还是在用实现Runnable接口 的方式在创建多线程。
因为你new Thread(mt).start();            new Thread(mt).start();  这两句用的构造函数是Thread(Runnable target)构造函数。
Thread本身也是实现了Runnable接口,所以你的MyThread也间接实现Runnable接口,所以MyThread的对象可以用作参数来创建Thread线程。   
     3.如果你把mt线程也开启的话就会看到效果,mt线程跟那两个匿名线程是不共享资源的。


评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
你的代码   想一个线程的构造函数传递了一个线程类对象   怎么实现的啊  根本没有这种构造函数 啊   Thread类的构造函数  只能接受Runnable的实现类  或者  线程组    你的代码好奇怪
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马