在我们开发的过程中常常会碰到多线程的问题,对于多线程的实现方式主要有两种:实现Runnable接口、继承Thread类。对于这两种多线程的实现方式也是有着一些差异。既然实现了多线程那必然离不开管理这些线程,当问题比简单时一个或者几个线程就OK了,也涉及不到效率问题。一旦线程数量多起来的时候,必然躲不过这些线程的创建与销毁,而往往这是很浪费时间的。这时就需要利用线程池来进行管理,既免去了我们创建线程和销毁线程的代码,也提高了程序的效率。下面针对以上问题做出相关讲解。
首先阐述实现Runnable的好处:
- java不允许多继承,因此实现了Runnable接口的类可以再继承其他类。
- 方便资源共享,即可以共享一个对象实例???(从很多博客中看到这样描述,但是此处有疑问,例子如下)
下面来通过具体代码来解释上述优点,网上很流行的买票系统,假设有10张票,首先通Thread来进行购买。代码如下:
public class TicketThread extends Thread{ private int ticket = 10; public void run(){ for(int i =0;i<10;i++){ synchronized (this){ if(this.ticket>0){ try { Thread.sleep(100); System.out.println(Thread.currentThread().getName()+"卖票---->"+(this.ticket--)); } catch (InterruptedException e) { e.printStackTrace(); } } } } } public static void main(String[] arg){ TicketThread t1 = new TicketThread(); new Thread(t1,"线程1").start(); new Thread(t1,"线程2").start(); //也达到了资源共享的目的,此处网上有各种写法,很多写法都是自圆其说,举一些特殊例子来印证自己的观点,然而事实却不尽如此。 } }
输出:
线程1卖票—->10
线程1卖票—->9
线程1卖票—->8
线程2卖票—->7
线程2卖票—->6
线程1卖票—->5
线程1卖票—->4
线程2卖票—->3
线程2卖票—->2
线程1卖票—->1
实现Runnable接口:
public class TicketRunnable implements Runnable{ private int ticket = 10; @Override public void run() { for(int i =0;i<10;i++){ //添加同步快 synchronized (this){ if(this.ticket>0){ try { //通过睡眠线程来模拟出最后一张票的抢票场景 Thread.sleep(100); System.out.println(Thread.currentThread().getName()+"卖票---->"+(this.ticket--)); } catch (Exception e) { e.printStackTrace(); } } } } } public static void main(String[] arg){ TicketRunnable t1 = new TicketRunnable(); new Thread(t1, "线程1").start(); new Thread(t1, "线程2").start(); } }输出:
线程1卖票—->10
线程1卖票—->9
线程1卖票—->8
线程1卖票—->7
线程2卖票—->6
线程2卖票—->5
线程2卖票—->4
线程2卖票—->3
线程2卖票—->2
线程2卖票—->1