黑马程序员技术交流社区

标题: 关于怎么实现多线程 [打印本页]

作者: 于振发    时间: 2013-9-26 01:53
标题: 关于怎么实现多线程
我知道java创建线程类的两中方式,一种是继承Thread类,一种是实现Runnable接口。
我想问的是在实际开发中,用那种方式好一些呢?
他们有什么区别呢?
有的人说使用第二种好,就是实现Runnable接口,这样推荐,只是为了避免java的单继承吗?
这两种方式在底层的实现有什么不同?
作者: 咕咕猫    时间: 2013-9-26 07:46
实现方式的好处:避免了单继承的局限性,在定义线程时,建议使用实现方式。
区别在于:继承Thread,线程代码存放在Thread子类run方法中 实现Runnable,线程代码存在接口的子类run方法中。
创建多条操作共享数据的时要用实现Runnable接口方式,只是建立单线程的话要求就没那么多了。
作者: hoyouly    时间: 2013-9-26 08:37
实现方式和继承方式怎么选择:建议使用实现方式,因为首先看API会发现,其实Thread类也实现了Runnable接口的,也就是说,Thread类中的run方法时实现的Runnable接口的run方法的,从某种意义上说,Runnable是Thread类的爹,我们是可以通过继承Thread类来实现多线程,那样我们就是Runnable接口的孙子辈了,而如果我们直接实现Runnable接口,那么就是Runnable接口的儿子。既然能当儿子,何必装孙子呢,是吧,为什么我们不直接去实现Runnable接口呢,就像毕老师说的那样:要穿一手鞋,能不穿二手甚至多手鞋就不穿。可能这个例子有点不恰当。但是从另一个java语法上看待这个问题,也是建议使用实现方式,而不是继承方式,因为如果一个类要想通过继承Thread类创建线程,那么这样的话,他就不能去继承其他的类了,java类中只能单继承,不能进行多继承。而要是通过实现Runnable接口的方式的话,就可以即继承父类,实现其他的接口,java中一个类可以实现多个接口。
实现方式好处:避免了单继承的局限性。故在定义线程时,建立使用实现方式。
继承Thread,  线程代码存放Thread子类run方法中。
实现Runnable,线程代码存在接口的子类的run方法。

这是我自己的一些理解,希望对你有用
作者: 杨修    时间: 2013-9-26 09:08
建议你对比一下售票的例子,其中从继承Thread到Runnable是怎么过度的,就知道Runnable的好处了。
另外,其他区别楼上都说了。
作者: wrswuxiaoyan    时间: 2013-9-26 09:41
我来分享下,我昨天一个总结,从thread到Runnable!

举例来说明吧,这样更志直观些

以火车票同时开4个窗口进行卖票为例:



但是运行的结果是这样的,请看下边截图



第一张票同时被第2个线程和第3个线程同时应用,在现实生活是不存在的啊,你想想同样的火车票不可能同时的卖给两个人吧!

第一张票同时被第2个线程和第3个线程同时应用,在现实生活是不存在的啊,你想想同样的火车票不可能同时的卖给两个人吧!

思考下这个问题怎么解决呢?

出现的原因:

出现这个问题的原因是,在main主方法中同时new出四个单线程的对象,当线程开启的时候,每个线程都会去调用一次run方法,每次调用的ticket变量都是100,都是从100循环开始的,这导致一张票同时卖给两个人的现象。


解决办法:

1、只要让int ticket=100称为一个静态的变量就可以了,但是,静态变量的生命周期太长,所以不建议用这种方法。

2、public static void main(String[] args)
{
mythread tic1=new mythread();
mythread tic2=new mythread();
mythread tic3=new mythread();
mythread tic4=new mythread();
tic1.start();
tic2.start();
tic3.start();
tic4.start();
}
在main主方法中一共new了四个不同的对象,在内存中就有了4个不同的空间,现在想办法让四个线程去共用一个对象,就可以解决这种情况了!怎么样实现呢,新的东西又引进了,咱们可以不继承Thread类,而去实现Runnable的接口,在main方法中

public static void main(String[] args)
{
mythread tic1=new mythread();
Thread t1=new Thread(tic1);
Thread t2=new Thread(tic1);
Thread t3=new Thread(tic1);
Thread t4=new Thread(tic1);
t1.start();
t2.start();
t3.start();
t4.start();
}
new出tic1对象,把这个对象全部给了new出的四个线程中,这样他们四个线程就共享了同一个tic1对象,

class mythread implements Runnable
{
public static int ticket=100;
public void run()
{
while(true)
{
if(ticket>0)
{
System.out.println(Thread.currentThread().getName()+"....."+ticket--);
}
}
}
}

最后总的代码是这样的

class mythread implements Runnable
{
public static int ticket=100;
public void run()
{
while(true)
{
if(ticket>0)
{
System.out.println(Thread.currentThread().getName()+"....."+ticket--);
}
}
}
}
class  threadDemo
{
public static void main(String[] args)
{
mythread tic1=new mythread();
Thread t1=new Thread(tic1);
Thread t2=new Thread(tic1);
Thread t3=new Thread(tic1);
Thread t4=new Thread(tic1);
t1.start();
t2.start();
t3.start();
t4.start();
}
}

作者: wrswuxiaoyan    时间: 2013-9-26 09:48
上边第一个图片不显示,我这里把代码复制下class mythread extends Thread
{
        public  int ticket=100;
        public void run()
        {
                while(true)
                {
                        if(ticket>0)
                        {
                                System.out.println(Thread.currentThread().getName()+"....."+ticket--);
                        }
                }
        }
}
class  threadDemo
{
        public static void main(String[] args)
        {
                mythread tic1=new mythread();
                mythread tic2=new mythread();
                mythread tic3=new mythread();
                mythread tic4=new mythread();
                tic1.start();
                tic2.start();
                tic3.start();
                tic4.start();
        }
}

以上我是举例说明的从Thread到Runnable接口的应用过程




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