1. 程式人生 > >使用Lock,wait/notify,Semaphore三種方式實現多執行緒通訊

使用Lock,wait/notify,Semaphore三種方式實現多執行緒通訊

java的多執行緒通訊有Lock,wait/notify,Semaphore三種方式,以一道常見面試題來簡單演示這三種多執行緒通訊方式。

兩個執行緒迴圈間隔列印指定內容,一個列印從1到52的數字,一個列印從A到Z的字母,列印輸出如下:

1
2
A
3
4

B

......

51
52
Z

使用Lock實現程式碼如下:

  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. publicclass ThreadCommunicationTest {    
  7.     privatefinal Lock lock = new ReentrantLock();    
  8.     privatefinal Condition conditionA = lock.newCondition();    
  9.     privatefinal Condition conditionB = lock.newCondition();    
  10.     privatestaticchar currentThread = 'A';    
  11.     publicstaticvoid main(String[] args) {    
  12.         ThreadCommunicationTest test = new ThreadCommunicationTest();    
  13.         ExecutorService service = Executors.newCachedThreadPool();    
  14.         service.execute(test.new RunnableA());    
  15.         service.execute(test.new
     RunnableB());    
  16.         service.shutdown();    
  17.     }    
  18.     privateclass RunnableA implements Runnable {    
  19.         publicvoid run() {    
  20.             for (int i = 1; i <= 52; i++) {    
  21.                 lock.lock();    
  22.                 try {    
  23.                     while (currentThread != 'A') {    
  24.                         try {    
  25.                             conditionA.await();    
  26.                         } catch (InterruptedException e) {    
  27.                             e.printStackTrace();    
  28.                         }    
  29.                     }    
  30.                     System.out.println(i);    
  31.                     if (i % 2 == 0) {    
  32.                         currentThread = 'B';    
  33.                         conditionB.signal();    
  34.                     }    
  35.                 } finally {    
  36.                     lock.unlock();    
  37.                 }    
  38.             }    
  39.         }    
  40.     }    
  41.     privateclass RunnableB implements Runnable {    
  42.         publicvoid run() {    
  43.             for (char c = 'A'; c <= 'Z'; c++) {    
  44.                 lock.lock();    
  45.                 try {    
  46.                     while (currentThread != 'B') {    
  47.                         try {    
  48.                             conditionB.await();    
  49.                         } catch (InterruptedException e) {    
  50.                             e.printStackTrace();    
  51.                         }    
  52.                     }    
  53.                     System.out.println(c);    
  54.                     currentThread = 'A';    
  55.                     conditionA.signal();    
  56.                 } finally {    
  57.                     lock.unlock();    
  58.                 }    
  59.             }    
  60.         }    
  61.     }    
  62. }    
使用wait/notify實現程式碼如下:
  1. import java.util.concurrent.ExecutorService;  
  2. import java.util.concurrent.Executors;  
  3. publicclass ThreadCommunicationTest2 {    
  4.     privatestaticchar currentThread = 'A';   
  5.     privatefinal Object t = new Object(); //使用一個同步物件保證兩個執行緒之間每一時刻只有一個執行緒工作
  6.     publicstaticvoid main(String[] args) {    
  7.         ThreadCommunicationTest2 test = new ThreadCommunicationTest2();    
  8.         ExecutorService service = Executors.newCachedThreadPool();    
  9.         service.execute(test.new RunnableA());    
  10.         service.execute(test.new RunnableB());    
  11.         service.shutdown();    
  12.     }    
  13.     privateclass RunnableA implements Runnable {  
  14.         publicvoid run() {    
  15.             for (int i = 1; i <= 52; i++) {    
  16.                 synchronized (t) {    
  17.                     if(currentThread != 'A'){    
  18.                         try {    
  19.                             t.wait();    
  20.                         } catch (InterruptedException e) {    
  21.                             e.printStackTrace();    
  22.                         }    
  23.                     }    
  24.                     System.out.println(i);    
  25.                     if (i % 2 == 0) {    
  26.                         currentThread = 'B';    
  27.                         t.notifyAll();    
  28.                     }    
  29.                 }    
  30.             }    
  31.         }  
  32.     }  
  33.     privateclass RunnableB implements Runnable {  
  34.         publicvoid run() {    
  35.             for (char c = 'A'; c <= 'Z'; c++) {   
  36.                 synchronized (t) {    
  37.                     if(currentThread != 'B'){    
  38.                         try {    
  39.                             t.wait();    
  40.                         } catch (InterruptedException e) {    
  41.                             e.printStackTrace();    
  42.                         }    
  43.                     }    
  44.                     System.out.println(c);    
  45.                     currentThread = 'A';    
  46.                     t.notifyAll();    
  47.                 }    
  48.             }    
  49.         }  
  50.     }  
  51. }  
使用Semaphore訊號量的程式碼如下:
  1. import java.util.concurrent.ExecutorService;  
  2. import java.util.concurrent.Executors;  
  3. import java.util.concurrent.Semaphore;  
  4. publicclass ThreadCommunicationTest3 {  
  5.     privatefinal Semaphore semap = new Semaphore(1);//建立一個只有1個許可的訊號量,保證兩個執行緒間每一時刻只有一個在工作
  6.     privatestaticchar currentThread = 'A';  
  7.     publicstaticvoid main(String[] args) {  
  8.         ThreadCommunicationTest3 test = new ThreadCommunicationTest3();  
  9.         ExecutorService service = Executors.newCachedThreadPool();  
  10.         service.execute(test.new RunnableA());  
  11.         service.execute(test.new RunnableB());  
  12.         service.shutdown();  
  13.     }  
  14.     privateclass RunnableA implements Runnable {  
  15.         publicvoid run() {  
  16.             for (int i = 1; i <