在程序开发中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下好处:
- 避免点继承的局限,一个类可以继承多个接口。
- 适合于资源的共享
模拟卖火车站情况说明资源共享问题
法一:继承Thread
//模拟3个窗口卖火车票,通过继承Thread实现 class MyThread extends Thread { private int ticket=5;//模拟3个窗口卖火车票 private String name; public MyThread(String name) { this.name=name; } public void run() { while(ticket>0) { ticket--; System.out.println(name+"卖出了1个票,还剩下"+ticket+"张票"); } } } public class ThreadTicket { public static void main(String[] args) { MyThread thread1=new MyThread("窗口A"); MyThread thread2=new MyThread("窗口B"); MyThread thread3=new MyThread("窗口C"); //启动3个线程,3个线程模拟3个卖票窗口 thread1.start(); thread2.start(); thread3.start(); } }
运行结果分析,实际是每个线程有自己的ticket为5,有自己的name,不是共享资源ticket=5
窗口C卖出了1个票,还剩下4张票
窗口C卖出了1个票,还剩下3张票
窗口A卖出了1个票,还剩下4张票
窗口A卖出了1个票,还剩下3张票
窗口A卖出了1个票,还剩下2张票
窗口A卖出了1个票,还剩下1张票
窗口A卖出了1个票,还剩下0张票
窗口C卖出了1个票,还剩下2张票
窗口C卖出了1个票,还剩下1张票
窗口C卖出了1个票,还剩下0张票
窗口B卖出了1个票,还剩下4张票
窗口B卖出了1个票,还剩下3张票
窗口B卖出了1个票,还剩下2张票
窗口B卖出了1个票,还剩下1张票
窗口B卖出了1个票,还剩下0张票
法二:继承Runnable接口
class MyThread1 implements Runnable { private int ticket=5;//模拟3个窗口卖火车票 public void run() { while(ticket>0) { ticket--; System.out.println(Thread.currentThread().getName()+"卖出了1个票,还剩下"+ticket+"张票"); } } } public class runnableTickect { public static void main(String[] args) { //使用Runnable定义的子类中没有start()方法,只有Thread类中才有 MyThread1 thread=new MyThread1(); //继承接口实现资源共享,是同一个变量ticket Thread th1=new Thread(thread, "window A"); Thread th2=new Thread(thread, "window B"); Thread th3=new Thread(thread, "window C"); //启动线程 th1.start(); th2.start(); th3.start(); } }
运行结果与分析,是同共享同一变量ticket=5,由于cpu抢占时间片有差异,可能结果多种多样
window B卖出了1个票,还剩下3张票
window C卖出了1个票,还剩下2张票
window A卖出了1个票,还剩下3张票
window C卖出了1个票,还剩下0张票
window B卖出了1个票,还剩下1张票