相关文章:
在日常开发过程中,除了使用线程池来创建线程外,我们还可以通过继承 Thread 类或者实现 Runnable 接口来创建线程,那么它们之间又有什么区别呢,这里让我们来一起深入了解下
一、举例说明
-
例子一 (继承 Thread 类)
public class MyThread extends Thread { private String name; private int ticket = 5; public MyThread(String name) { this.name = name; } @Override public void run() { do { System.out.println("总共【" + ticket-- + "】张票," + this.name+ "卖出一张票,还剩【" + ticket + "】张票"); } while (ticket >= 1); } }
public class ThreadDemo { public static void main(String[] args) { new MyThread("一号窗口").start(); new MyThread("二号窗口").start(); new MyThread("三号窗口").start(); } } // 总共【5】张票,一号窗口卖出一张票,还剩【4】张票 // 总共【5】张票,三号窗口卖出一张票,还剩【4】张票 // 总共【5】张票,二号窗口卖出一张票,还剩【4】张票 // 总共【4】张票,三号窗口卖出一张票,还剩【3】张票 // 总共【4】张票,一号窗口卖出一张票,还剩【3】张票 // 总共【3】张票,一号窗口卖出一张票,还剩【2】张票 // 总共【3】张票,三号窗口卖出一张票,还剩【2】张票 // 总共【4】张票,二号窗口卖出一张票,还剩【3】张票 // 总共【2】张票,三号窗口卖出一张票,还剩【1】张票 // 总共【2】张票,一号窗口卖出一张票,还剩【1】张票 // 总共【1】张票,三号窗口卖出一张票,还剩【0】张票 // 总共【3】张票,二号窗口卖出一张票,还剩【2】张票 // 总共【1】张票,一号窗口卖出一张票,还剩【0】张票 // 总共【2】张票,二号窗口卖出一张票,还剩【1】张票 // 总共【1】张票,二号窗口卖出一张票,还剩【0】张票
-
如上所示,我们定义了一个 MyThread 类使其继承 Thread 类,在 main() 方法中,我们 new 了三个 MyThread 类并调用其 start() 方法
-
由输出可知,三个窗口各自卖出了 5 张票,即总共卖出了 15 张票
-
-
例子二 (实现 Runnable 接口)
public class MyRunnable implements Runnable { private int ticket = 5; private boolean isOk = true; @Override public synchronized void run() { do { if (!isOk) { this.notifyAll(); } System.out.println("总共【" + ticket-- + "】张票," + Thread.currentThread().getName() + "卖出一张票,还剩【" + ticket + "】张票"); try { isOk = false; if (ticket == 0) { break; } this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } while (ticket >= 1); } }
public class RunnableDemo { public static void main(String[] args) { MyRunnable mr = new MyRunnable(); new Thread(mr, "一号窗口").start(); new Thread(mr, "二号窗口").start(); new Thread(mr, "三号窗口").start(); } } // 总共【5】张票,一号窗口卖出一张票,还剩【4】张票 // 总共【4】张票,三号窗口卖出一张票,还剩【3】张票 // 总共【3】张票,二号窗口卖出一张票,还剩【2】张票 // 总共【2】张票,三号窗口卖出一张票,还剩【1】张票 // 总共【1】张票,一号窗口卖出一张票,还剩【0】张票
-
如上所示,我们定义了一个 MyRunnable 类使其实现了 Runnable 接口,在 main() 方法中,我们 new 了一个 MyRunnable 类,并将其作为参数传入到 new 的三个线程当中
-
由输出可知,三个窗口一共卖了 5 张票
-
二、结果分析
-
例子一中,三个线程 (窗口) 分别使用其各自的资源,也就是说分别给三个线程 (窗口) 5 张票去进行处理,各自完成各自的任务
- 由于 Thread 类本生实现了 Runnable 接口,因此也可以跟例子二一样,创建三个线程并传入同一个 MyThread,从而实现资源共享
-
例子二中,三个线程 (窗口) 共享了一个资源,也就是说总共 5 张票给三个线程 (窗口) 去进行处理,共同完成任务
- 由于三个线程共享一个资源,会存在线程安全的问题,因此使用了 synchronized 来对 run() 方法进行加锁,从而保证线程安全
三、归纳总结
-
Thread 类实现了 Runnable 接口,使得 run() 方法支持多线程
-
Thread 是类,Runnable 是接口
-
由于类的单一继承原则,推荐使用 Runnable 接口