您的位置:首页 > 编程语言 > Java开发

JAVA多线程之Thread VS Runnable

2015-10-28 17:55 483 查看
1,在java中开发线程主要有两种方式,一种是继承自Thread类,另一种是实现Runnable接口。

2,线程创建的两种方式:

a,继承Thread类:

class MyThread eatends Thread{

......

@Override

public void run(){

}

}

MyThread mt=new MyThread();

mt.start();

b,实现Runnable接口:

class MyThread implements Runnable{

......

@Override

public void run(){

}

}

MyThread mt=new MyThread();

Thread th=new Thread(mt);

td.start();

说明:在继承Thread类的main方法中,只需创建线程(MyThread mt=new MyThread()),

然后开启线程(mt.start())即可,但在实现Runnable接口的main方法中,还要向线程

(Thread th=new Thread(mt))中传递一个参数mt,mt为线程类(MyThread)实例化

的一个对象。

3,两种创建方式的比较:

a,Runnable方式可以避免Thread方式由于java单继承带来的缺陷,就是每次只能继承一个Thread。

b,Runnable的代码可以被多个线程(Runnable实例)共享,适合多个线程处理同一资源的情况。

4,关于这两种方式的区别,很难说明白,下面我用售票系统的代码来分析:

场景描述:假设春节来临,广州到北京的火车票还有5张,现在通过3个售票窗口来出售,这三个

售票窗口同时开放,随机的出售车票

代码实现:

a,首先通过继承Thread创建线程,来完成这项工作,然后分析结果,代码如下:

class MyThread extends Thread{

//一共有五张车票

private int TicketsCount=5;

//窗口,也就是线程的名字

private String name;

public MyThread(String name){

this.name=name;

}

@Override

public void run() {

while (TicketsCount>0) {

TicketsCount--;

System.out.println(name+"卖了一张票,剩余票数为:"+TicketsCount);

}

}

}

public class TicketsThread {

public static void main(String[] args) {

//创建三个线程,模拟三个售票窗口

MyThread mt1=new MyThread("窗口1");

MyThread mt2=new MyThread("窗口2");

MyThread mt3=new MyThread("窗口3");

//启动三个线程,开始卖票

mt1.start();

mt2.start();

mt3.start();

}

}

执行结果:

窗口1卖了一张票,剩余票数为:4

窗口2卖了一张票,剩余票数为:4

窗口1卖了一张票,剩余票数为:3

窗口2卖了一张票,剩余票数为:3

窗口1卖了一张票,剩余票数为:2

窗口2卖了一张票,剩余票数为:2

窗口1卖了一张票,剩余票数为:1

窗口2卖了一张票,剩余票数为:1

窗口3卖了一张票,剩余票数为:4

窗口3卖了一张票,剩余票数为:3

窗口1卖了一张票,剩余票数为:0

窗口3卖了一张票,剩余票数为:2

窗口3卖了一张票,剩余票数为:1

窗口3卖了一张票,剩余票数为:0

窗口2卖了一张票,剩余票数为:0

嗯?总共有5张票,现在3个售票窗口怎么卖出了15张票?仔细观察我们会发现,其实每个售票窗口

都卖出了5张票。这是怎么回事?其实这是java单继承所带来的缺陷,在创建线程时,3个窗口各自

创建了一个线程,每个线程都有自己的TicketsCount和name,各自执行了自己的run方法,所以在执

行程序时每个售票窗口都卖出了5张票。

b,通过实现Runnable接口的方法,来完成这项工作,代码如下:

class MyThread2 implements Runnable{

private int TicketsCount=5;

@Override

public void run() {

while (TicketsCount>0) {

TicketsCount--;

System.out.println(Thread.currentThread().getName()+"卖出了一张票,剩余票数为:

"+TicketsCount);

}

}

}

public class TicketsRunnable{

public static void main(String[] args) {

//实例化对象

MyThread2 mt=new MyThread2();

//创建三个线程,模拟三个售票窗口

Thread th1=new Thread(mt,"窗口1");

Thread th2=new Thread(mt,"窗口2");

Thread th3=new Thread(mt,"窗口3");

//启动三个线程,开始卖票

th1.start();

th2.start();

th3.start();

}

}

执行结果:

窗口1卖出了一张票,剩余票数为:4

窗口2卖出了一张票,剩余票数为:2

窗口2卖出了一张票,剩余票数为:0

窗口3卖出了一张票,剩余票数为:3

窗口1卖出了一张票,剩余票数为:1

我们会发现,通过实现Runnable接口的方法所得到的结果正是我们想要的。MyThread2是实现

Runnable接口的,先通过类实例化出对象(mt),然后再把对象作为参数传递给3个线程对象,

也就是说3个线程对象传递的是同一个Runnable对象,从而实现了资源(TicketsCount=5)共

享,所以三个售票窗口总共卖出了5张票。

通过这个例子,我们已经清楚了Runnable和Thread 的区别。还需要强调一点,无论是继承

Thread类,还是实现Runnable方法,都需要重写run()方法,然后在run()方法了实现要做的事

情,最后通过start()方法启动线程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: