線程的兩種實現方式,以及區別

-  讓類成爲線程類有兩種方式,實現Runnable接口,以及繼承Thread類(類中實現了Runnable接口,還提供了一些額外的方法)。 java

1、Runnable相對優點:

  • java的單繼承,當繼承了Thread類,則不能繼承其餘類,而實現Runnable接口能夠

  • 實現Runnable接口的線程類的多個線程,能夠訪問同一變量,而Thread則不能(多窗口買票問題)

緣由:兩種方式啓動方式不一樣:多線程

 

  • Runnable線程類是實例化一個對象o以後,經過屢次new Thread(o).start();啓動多個線程,而這幾個線程屬於一個對象,對象的成員變量是同一個。
  • Thread線程類啓動多個線程須要 new MyThread().start();每一個線程啓動都對應多個對象,他們的成員變量是獨立的。

 測試代碼以下:ide

(1)實現Runnable:測試

 1 package com.loan.entity;  2  
 3 import lombok.Data;  4  
 5 @Data  6 public class Test2 implements Runnable{  7 private int ticket=100;  8 @Override  9 public void run() { 10     // TODO Auto-generated method stub
11     while(true){ 12         if(ticket>0){ 13             System.out.println(Thread.currentThread().getName()+"...is saling,餘票:"+ticket--); 14  } 15  } 16 } 17 public static void main(String[] args) { 18     Test2 t=new Test2();//只能使用同一個t
19     new Thread(t).start(); 20     new Thread(t).start(); 21     new Thread(t).start(); 22     new Thread(t).start(); 23 } 24 }

 

運行結果:

(2)繼承Thread

 1 package com.loan.entity;  2  
 3 public class Test3 extends Thread{  4     int ticket=100;  5     public void run(){  6         while(true){  7             if(ticket>0){  8                 System.out.println(Thread.currentThread().getName()+"...is saling,餘票:"+ticket--);  9  } 10  } 11  } 12     public static void main(String[] args) { 13         new Test3().start(); 14         new Test3().start(); 15         new Test3().start(); 16         new Test3().start(); 17  } 18 }

很明顯,上面這種方式是錯誤的!

繼承Thread類也能夠經過內部類發方式實現。代碼以下:

 1 package com.loan.entity;  2  
 3 public class Test3{  4     private  int ticket=100;  5     class InnerClass extends Thread{  6         private Test3 t3;  7  InnerClass(Test3 t){  8             t3=t;  9  } 10         public void run(){ 11             while(true){ 12                 if(ticket>0){ 13                     ticket--; 14                     System.out.println(Thread.currentThread().getName()+"...is saling,餘票:"+ticket); 15  } 16  } 17  } 18  } 19     public static void main(String[] args) { 20         Test3 test3=new Test3(); 21         Thread t1=test3.new InnerClass(test3); 22         Thread t2=test3.new InnerClass(test3); 23         Thread t3=test3.new InnerClass(test3); 24         Thread t4=test3.new InnerClass(test3); 25         t1.setName("t1"); 26         t2.setName("t2"); 27         t3.setName("t3"); 28         t4.setName("t4"); 29  t1.start(); 30  t2.start(); 31  t3.start(); 32  t4.start(); 33  } 34 }

 

運行結果:

2、Thread優點

一、使用線程的方法方便一些,例如:獲取線程的Id(Thread.currentThread().getId())、線程名(Thread.currentThread().getName())、線程狀態(Thread.currentThread().getState())等

二、操做同一變量,可是線程調用run方法內容不一樣時,使用Thread內部類的方式進行,例如生產者、消費者模式

生產者消費者多線程例子:

 1 package com.loan.entity;  2  
 3 public class Store {  4     private final int MAX_SIZE=2;//倉庫總共可存放貨物
 5     private int count=0;//當前倉庫貨物
 6     public synchronized void add() throws InterruptedException{  7         while(count>=MAX_SIZE){  8             System.out.println("倉庫已滿");  9             System.out.println(Thread.currentThread().getName()+"等待中。。。。"); 10             this.wait(); 11  } 12             count++; 13             System.out.println(Thread.currentThread().getName()+"存入倉庫,當前貨物數:"+count); 14             this.notify(); 15  } 16     public synchronized void remove() throws InterruptedException{ 17         while(count<=0){ 18             System.out.println("倉庫空了"); 19             System.out.println(Thread.currentThread().getName()+"等待中。。。。"); 20             this.wait(); 21  } 22             count--; 23             System.out.println(Thread.currentThread().getName()+"取出貨物,當前貨物數:"+count); 24             this.notify(); 25  } 26     public static void main(String[] args) { 27         Store s=new Store(); 28         Thread producer1=s.new Producer(s);//成員內部類需經過對象訪問
29         Thread producer2=s.new Producer(s); 30         Thread consumer1=s.new Consumer(s); 31         Thread consumer2=s.new Consumer(s); 32         producer1.setName("producer1");//利用Thread中的方法
33         producer2.setName("producer2"); 34         consumer1.setName("consumer1"); 35         consumer2.setName("consumer2"); 36  producer1.start(); 37  producer2.start(); 38  consumer1.start(); 39  consumer2.start(); 40  } 41     class Producer extends Thread{ 42         private Store store; 43  Producer(Store s){ 44             store=s; 45  } 46         public void run(){ 47             while(true){ 48                 try { 49  store.add(); 50                     Thread.sleep(10000); 51                 } catch (InterruptedException e) { 52                     // TODO Auto-generated catch block
53  e.printStackTrace(); 54  } 55  } 56  } 57  } 58     class Consumer extends Thread{ 59         private Store store; 60  Consumer(Store s){ 61             store=s; 62  } 63         public void run(){ 64             while(true){ 65                 try { 66  store.remove(); 67                     Thread.sleep(15000); 68                 } catch (InterruptedException e) { 69                     // TODO Auto-generated catch block
70  e.printStackTrace(); 71  } 72  } 73  } 74  } 75 }

 

運行結果:

相關文章
相關標籤/搜索