java中Runnable和Thread的区别

来源:互联网 发布:linux不能初始化opengl 编辑:程序博客网 时间:2024/05/23 18:07

Java中线程的创建有两种方式:

 

1.  通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中

2.  通过实现Runnable接口,实例化Thread类

 

    在实际应用中,我们经常用到多线程,如车站的售票系统,车站的各个售票口相当于各个线程。当我们做这个系统的时候可能会想到两种方式来实现,继承Thread类或实现Runnable接口,现在看一下这两种方式实现的两种结果。

class MyThread extends Thread{        private int ticket = 10;    private String name;    public MyThread(String name){        this.name =name;    }        public void run(){        for(int i =0;i<500;i++){            if(this.ticket>0){               System.out.println(Thread.currentThread().getName()+"卖票---->"+(this.ticket--));            }        }    }}public class ThreadDemo {        public static void main(String[] args) {        MyThread mt1= new MyThread("一号窗口");        MyThread mt2= new MyThread("二号窗口");        MyThread mt3= new MyThread("三号窗口");        mt1.start();        mt2.start();        mt3.start();    }}

这里说下用run启动和start启动的区别:

run启动是正常启动,而start启动会进行资源协调。看源码可以知道,start方法加了同步锁synchronized。所以在运行时保证了数据的正确性。

结果如下:

一号窗口卖票---->10一号窗口卖票---->9二号窗口卖票---->10一号窗口卖票---->8一号窗口卖票---->7一号窗口卖票---->6三号窗口卖票---->10一号窗口卖票---->5一号窗口卖票---->4一号窗口卖票---->3一号窗口卖票---->2一号窗口卖票---->1二号窗口卖票---->9二号窗口卖票---->8三号窗口卖票---->9三号窗口卖票---->8三号窗口卖票---->7三号窗口卖票---->6三号窗口卖票---->5三号窗口卖票---->4三号窗口卖票---->3三号窗口卖票---->2三号窗口卖票---->1二号窗口卖票---->7二号窗口卖票---->6二号窗口卖票---->5二号窗口卖票---->4二号窗口卖票---->3二号窗口卖票---->2二号窗口卖票---->1
可以发现,虽然在交替运行,但是3个线程的数据并没有共享!这是因为虽然实例化了3个线程,但是3个线程都拥有各自的属性(10张票)。

通过实现Runnable接口的代码如下:

class MyThread1 implements Runnable{    private int ticket =10;    private String name;    public void run(){        for(int i =0;i<500;i++){            if(this.ticket>0){                System.out.println(Thread.currentThread().getName()+"卖票---->"+(this.ticket--));            }        }    }}public class RunnableDemo {        public static void main(String[] args) {        // TODO Auto-generated method stub        //设计三个线程         Runnable mt = new MyThread1();         Thread t1 = new Thread(mt,"一号窗口");         Thread t2 = new Thread(mt,"二号窗口");         Thread t3 = new Thread(mt,"三号窗口");//         MyThread1 mt2 = new MyThread1();//         MyThread1 mt3 = new MyThread1();         t1.start();         t2.start();         t3.start();    }}
结果如下:
一号窗口卖票---->10三号窗口卖票---->9三号窗口卖票---->7三号窗口卖票---->5三号窗口卖票---->4三号窗口卖票---->3三号窗口卖票---->2三号窗口卖票---->1一号窗口卖票---->8二号窗口卖票---->6
在这里,通过实现runnable接口,则实现了资源共享!

总结: 两者之间的区别,用Runnable方式可以有以下意义

  • 避免点继承的局限,一个类可以继承/实现多个接口。
  • 适合于资源的共享
PS:注意,Thread类也是实现了Runnable接口的,所以,只要是通过用其他线程来运行目标线程的方式都属于通过接口的方式实现多线程!  即:通过 new Thread(Runnable target)方式,都是属于接口方式!


文章参考来源:http://mars914.iteye.com/blog/1508429