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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

实现多线程的两种方式,区别和好处有哪些

7 个回复

正序浏览
{:soso_e179:}
回复 使用道具 举报
王家俊 黑马帝 2011-10-9 00:04:05
7#
Thread是类,Runnable是接口,创建线程这两中方法都可以。但由于接口具有扩展功能,你在实现一个接口的同时又可以继承其他类,也就是说接口可以多继承而类只可以但继承,所有我们一般选择接口。所有这里就选择实现Runnable接口来创建线程了。例如类A实现Runnable的同时还可以继承一个XXX类来创建线程类,这就让他的功能更强大了,但若类A继承Thread类来创建线程的话他就不可以继承XXX类了,这就降低了他的功能。

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
一种是子类继承Thread类,子类调用start()方法开启一条线程;另一种是实现Runnable接口,但是Runnable接口是没有start()方法的,仍需要用到Thread实例对象调用start()方法开启线程,对比而言,实际开发基本都是用实现Runnable接口,因为继承父类,就局限了扩展性能,而且子类继承Thread类,子类的实例对象是唯一的,在多线程中要满足子类内部数据共享只能用静态数据,由于Thread(Runnable target) 构造方法接受一个Runnable接口实现类,一个Runnable接口实现类里的run()方法可以由多个线程启用,非常容易达到数据共享

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
一种从Thread类继承,一种实现Runnable接口,一般用后者。
回复 使用道具 举报
楼上说的不错。{:soso_e113:}
其实实现Runnable接口相对于继承Thread类来说,

(1)适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码,数据有效的分离,较好地体现了面向对象的设计思想。
(2)可以避免由于Java的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了。
(3)有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程操作相同的数据,与它们的代码无关。当共享访问相同的对象是,即它们共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例。

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
本帖最后由 林国锋 于 2011-10-8 14:44 编辑

一种是扩展java.lang.Thread类
另一种是实现java.lang.Runnable接口

区别就是:第一种是扩展,第二种是实现
好处就是:
在实际开发中通常以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类可以避免继承的局限,一个类可以继承多个接口,适合于资源的共享。

以卖票程序为例,通过Thread类完成:
package org.demo.dff;
class MyThread extends Thread{
    private int ticket=10;
    public void run(){
        for(int i=0;i<20;i++){
            if(this.ticket>0){
                System.out.println("賣票:ticket"+this.ticket--);
            }
        }
    }
};
下面通过三个线程对象,同时卖票:
package org.demo.dff;
public class ThreadTicket {
    public static void main(String[] args) {
        MyThread mt1=new MyThread();
        MyThread mt2=new MyThread();
        MyThread mt3=new MyThread();
        mt1.start();//每个线程都各卖了10张,共卖了30张票
        mt2.start();//但实际只有10张票,每个线程都卖自己的票
        mt3.start();//没有达到资源共享
    }
}
如果用Runnable就可以实现资源共享,下面看例子:
package org.demo.runnable;
class MyThread implements Runnable{
    private int ticket=10;
    public void run(){
        for(int i=0;i<20;i++){
            if(this.ticket>0){
                System.out.println("賣票:ticket"+this.ticket--);
            }
        }
    }
}
package org.demo.runnable;
public class RunnableTicket {
    public static void main(String[] args) {
        MyThread mt=new MyThread();
        new Thread(mt).start();//同一个mt,但是在Thread中就不可以,如果用同一
        new Thread(mt).start();//个实例化对象mt,就会出现异常
        new Thread(mt).start();
    }
};
虽然现在程序中有三个线程,但是一共卖了10张票,也就是说使用Runnable实现多线程可以达到资源共享目的。

Runnable接口和Thread之间的联系:
public class Thread extends Object implements Runnable
发现Thread类也是Runnable接口的子类。

评分

参与人数 1技术分 +2 收起 理由
admin + 2

查看全部评分

回复 使用道具 举报
本帖最后由 zhousaowen 于 2011-10-8 15:30 编辑

还有一种jdk1.5线程并发库,线程池:
Executors,查看jdk文档就能看到有很多的方法,可以得到一个线程池。
你只要把任务交个线程池,就可以了。新技术,很强悍。
public static void main(String[] args) {
                // TODO Auto-generated method stub
        ExecutorService pool=Executors.newCachedThreadPool(); //构造线程池
        for(int i=0;i<10;i++){
                final int taskid=i;
        pool.execute(new Runnable(){//把任务交给线程池

                        @Override
                        public void run() {
                                // TODO Auto-generated method stub
                                for(int i=0;i<10;i++){
                                        System.out.println(Thread.currentThread().getName()+
                                                        "is execute task "+ taskid+"for"+i
                                                        +"times !");
                                       
                                }
                        }
               
        });
        }
            pool.shutdown();
        }

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马