Thread和Runnable的区别

时间:2021-11-14 17:34:03
一共有5张车票,启动三个线程作为3个窗口同时卖出,每次卖出一张 总数减去一张:

   自定义线程MyThread继承thread类:

class MyThread extends Thread{
private Integer 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) {
// TODO Auto-generated method stub
MyThread mt1 = new MyThread("窗口一");
MyThread mt2 = new MyThread("窗口二");
MyThread mt3 = new MyThread("窗口三");
mt1.start();
mt2.start();
mt3.start();
}

}

结果如下:

窗口二卖了一张票  余票还有4张
窗口一卖了一张票  余票还有4张
窗口三卖了一张票  余票还有4张
窗口一卖了一张票  余票还有3张
窗口二卖了一张票  余票还有3张
窗口一卖了一张票  余票还有2张
窗口三卖了一张票  余票还有3张
窗口一卖了一张票  余票还有1张
窗口二卖了一张票  余票还有2张
窗口一卖了一张票  余票还有0张
窗口三卖了一张票  余票还有2张
窗口三卖了一张票  余票还有1张
窗口二卖了一张票  余票还有1张
窗口三卖了一张票  余票还有0张
窗口二卖了一张票  余票还有0张

结果:总共卖出了15张票

自定义线程MyThread实现Runnable接口:

class MyThread1 implements Runnable{

private Integer TicketsCount = 5;

@Override
public void run() {
shoupiao();
}
private void shoupiao() {
// TODO Auto-generated method stub
while(TicketsCount > 0){
TicketsCount--;
System.out.println(Thread.currentThread().getName()+"卖了1张票,剩余" + TicketsCount + "张票");
}

}

}
public class TicketsRunnable {

public static void main(String [] args){
MyThread1 mt = new MyThread1();
Thread th1 = new Thread(mt,"窗口一");
Thread th2 = new Thread(mt,"窗口二");
Thread th3 = new Thread(mt,"窗口三");
th1.start();
th2.start();
th3.start();
}
}

输出结果:

窗口一卖了1张票,剩余4张票
窗口三卖了1张票,剩余3张票
窗口二卖了1张票,剩余2张票
窗口三卖了1张票,剩余1张票
窗口一卖了1张票,剩余0张票

结果:总共卖出了5张票

结论:

1、Runnable方式可以避免Thread方式由于单继承特性带来的缺陷。

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

3、从本质上来说:Thread也是实现Runnable接口的,相当于对Runnable进行了一次包装,最终被线程执行的任务是Runnable而非Thread。Thread中有一个Runnable类型的target字段,代表要被执行在这个子线程中的任务,当启动一个线程的时候,如果target不为空,Runnable就会执行这个target的run函数,否则就会执行默认的run函数。