使用Lock,wait/notify,Semaphore三種方式實現多線程通信

Java的多線程通信有Lock,wait/notify,Semaphore三種方式,以一道常見面試題來簡單演示這三種多線程通信方式。

兩個線程循環間隔打印指定內容,一個打印從1到52的數字,一個打印從A到Z的字母,打印輸出如下:

1
2
A
3
4

B

......

51
52
Z

使用Lock實現代碼如下:

[java] view plain copy
  1. import java.util.concurrent.ExecutorService;  
  2. import java.util.concurrent.Executors;  
  3. import java.util.concurrent.locks.Condition;  
  4. import java.util.concurrent.locks.Lock;  
  5. import java.util.concurrent.locks.ReentrantLock;  
  6.   
  7. public class ThreadCommunicationTest {    
  8.         
  9.     private final Lock lock = new ReentrantLock();    
  10.     
  11.     private final Condition conditionA = lock.newCondition();    
  12.     private final Condition conditionB = lock.newCondition();    
  13.     
  14.     private static char currentThread = 'A';    
  15.     
  16.     public static void main(String[] args) {    
  17.     
  18.         ThreadCommunicationTest test = new ThreadCommunicationTest();    
  19.     
  20.         ExecutorService service = Executors.newCachedThreadPool();    
  21.     
  22.         service.execute(test.new RunnableA());    
  23.         service.execute(test.new RunnableB());    
  24.     
  25.         service.shutdown();    
  26.     
  27.     }    
  28.     
  29.     private class RunnableA implements Runnable {    
  30.         public void run() {    
  31.             for (int i = 1; i <= 52; i++) {    
  32.                 lock.lock();    
  33.     
  34.                 try {    
  35.                     while (currentThread != 'A') {    
  36.                         try {    
  37.                             conditionA.await();    
  38.                         } catch (InterruptedException e) {    
  39.                             e.printStackTrace();    
  40.                         }    
  41.                     }    
  42.     
  43.                     System.out.println(i);    
  44.                     if (i % 2 == 0) {    
  45.                         currentThread = 'B';    
  46.                         conditionB.signal();    
  47.                     }    
  48.                 } finally {    
  49.                     lock.unlock();    
  50.                 }    
  51.             }    
  52.     
  53.         }    
  54.     
  55.     }    
  56.     
  57.     private class RunnableB implements Runnable {    
  58.         public void run() {    
  59.             for (char c = 'A'; c <= 'Z'; c++) {    
  60.                 lock.lock();    
  61.                 try {    
  62.                     while (currentThread != 'B') {    
  63.                         try {    
  64.                             conditionB.await();    
  65.                         } catch (InterruptedException e) {    
  66.                             e.printStackTrace();    
  67.                         }    
  68.                     }    
  69.     
  70.                     System.out.println(c);    
  71.                     currentThread = 'A';    
  72.                     conditionA.signal();    
  73.                 } finally {    
  74.                     lock.unlock();    
  75.                 }    
  76.             }    
  77.     
  78.         }    
  79.     
  80.     }    
  81. }    
使用wait/notify實現代碼如下:

[java] view plain copy
  1. import java.util.concurrent.ExecutorService;  
  2. import java.util.concurrent.Executors;  
  3.   
  4.   
  5. public class ThreadCommunicationTest2 {    
  6.       
  7.     private static char currentThread = 'A';   
  8.     private final Object t = new Object(); //使用一個同步對象保證兩個線程之間每一時刻只有一個線程工作  
  9.         
  10.     public static void main(String[] args) {    
  11.         ThreadCommunicationTest2 test = new ThreadCommunicationTest2();    
  12.         ExecutorService service = Executors.newCachedThreadPool();    
  13.           
  14.         service.execute(test.new RunnableA());    
  15.         service.execute(test.new RunnableB());    
  16.     
  17.         service.shutdown();    
  18.     }    
  19.       
  20.     private class RunnableA implements Runnable {  
  21.         public void run() {    
  22.             for (int i = 1; i <= 52; i++) {    
  23.                 synchronized (t) {    
  24.                     if(currentThread != 'A'){    
  25.                         try {    
  26.                             t.wait();    
  27.                         } catch (InterruptedException e) {    
  28.                             e.printStackTrace();    
  29.                         }    
  30.                     }    
  31.                     System.out.println(i);    
  32.                     if (i % 2 == 0) {    
  33.                         currentThread = 'B';    
  34.                         t.notifyAll();    
  35.                     }    
  36.                 }    
  37.             }    
  38.         }  
  39.     }  
  40.       
  41.     private class RunnableB implements Runnable {  
  42.         public void run() {    
  43.             for (char c = 'A'; c <= 'Z'; c++) {   
  44.                 synchronized (t) {    
  45.                     if(currentThread != 'B'){    
  46.                         try {    
  47.                             t.wait();    
  48.                         } catch (InterruptedException e) {    
  49.                             e.printStackTrace();    
  50.                         }    
  51.                     }    
  52.                     System.out.println(c);    
  53.                     currentThread = 'A';    
  54.                     t.notifyAll();    
  55.                 }    
  56.             }    
  57.         }  
  58.     }  
  59.     
  60. }  
使用Semaphore信號量的代碼如下:

[java] view plain copy
  1. import java.util.concurrent.ExecutorService;  
  2. import java.util.concurrent.Executors;  
  3. import java.util.concurrent.Semaphore;  
  4.   
  5. public class ThreadCommunicationTest3 {  
  6.   
  7.     private final Semaphore semap = new Semaphore(1);//創建一個只有1個許可的信號量,保證兩個線程間每一時刻只有一個在工作  
  8.   
  9.     private static char currentThread = 'A';  
  10.   
  11.     public static void main(String[] args) {  
  12.   
  13.         ThreadCommunicationTest3 test = new ThreadCommunicationTest3();  
  14.   
  15.         ExecutorService service = Executors.newCachedThreadPool();  
  16.   
  17.         service.execute(test.new RunnableA());  
  18.         service.execute(test.new RunnableB());  
  19.   
  20.         service.shutdown();  
  21.   
  22.     }  
  23.   
  24.     private class RunnableA implements Runnable {  
  25.         public void run() {  
  26.             for (int i = 1; i <= 52; i++) {  
  27.                 try {  
  28.                     semap.acquire();  
  29.                     while (currentThread != 'A') {  
  30.                         semap.release();  
  31.                     }  
  32.                     System.out.println(i);  
  33.                     if (i % 2 == 0) {  
  34.                         currentThread = 'B';  
  35.                     }  
  36.                 } catch (Exception e) {  
  37.                     e.printStackTrace();  
  38.                 } finally {  
  39.                     semap.release();  
  40.                 }  
  41.             }  
  42.         }  
  43.     }  
  44.   
  45.     private class RunnableB implements Runnable {  
  46.         public void run() {  
  47.             for (char c = 'A'; c <= 'Z'; c++) {  
  48.                 try {  
  49.                     semap.acquire();  
  50.                     while (currentThread != 'B') {  
  51.                         semap.release();  
  52.                     }  
  53.                     System.out.println(c);  
  54.                     currentThread = 'A';  
  55.                 } catch (Exception e) {  
  56.                     e.printStackTrace();  
  57.                 } finally {  
  58.                     semap.release();  
  59.                 }  
  60.             }  
  61.         }  
  62.   
  63.     }  
  64. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章