Java多線程之Lock的使用


http://blog.csdn.net/huang_xw/article/details/7090177
[java]  view plain  copy
 
 print?
  1. import java.util.concurrent.ExecutorService;  
  2. import java.util.concurrent.Executors;  
  3. import java.util.concurrent.Future;  
  4. import java.util.concurrent.locks.Lock;  
  5. import java.util.concurrent.locks.ReadWriteLock;  
  6. import java.util.concurrent.locks.ReentrantLock;  
  7. import java.util.concurrent.locks.ReentrantReadWriteLock;  
  8.   
  9. /** 
  10.  * Lockers 
  11.  * 在多線程編程里面一個重要的概念是鎖定,如果一個資源是多個線程共享的,為了保證數據的完整性, 
  12.  * 在進行事務性操作時需要將共享資源鎖定,這樣可以保證在做事務性操作時只有一個線程能對資源進行操作, 
  13.  * 從而保證數據的完整性。在5.0以前,鎖定的功能是由Synchronized關鍵字來實現的。 
  14.  */  
  15. public class Lockers {  
  16.       
  17.     /** 
  18.      * 測試Lock的使用。在方法中使用Lock,可以避免使用Synchronized關鍵字。 
  19.      */  
  20.     public static class LockTest {  
  21.   
  22.         Lock lock = new ReentrantLock();// 鎖  
  23.         double value = 0d; // 值  
  24.         int addtimes = 0;  
  25.   
  26.         /** 
  27.          * 增加value的值,該方法的操作分為2步,而且相互依賴,必須實現在一個事務中 
  28.          * 所以該方法必須同步,以前的做法是在方法聲明中使用Synchronized關鍵字。 
  29.          */  
  30.         public void addValue(double v) {  
  31.             lock.lock();// 取得鎖  
  32.             System.out.println("LockTest to addValue: " + v + "   "  
  33.                     + System.currentTimeMillis());  
  34.             try {  
  35.                 Thread.sleep(1000);  
  36.             } catch (InterruptedException e) {  
  37.             }  
  38.             this.value += v;  
  39.             this.addtimes++;  
  40.             lock.unlock();// 釋放鎖  
  41.         }  
  42.   
  43.         public double getValue() {  
  44.             return this.value;  
  45.         }  
  46.     }  
  47.     public static void testLockTest() throws Exception{  
  48.         final LockTest lockTest = new LockTest();  
  49.         // 新建任務1,調用lockTest的addValue方法  
  50.         Runnable task1 = new Runnable(){  
  51.             public void run(){  
  52.                 lockTest.addValue(55.55);  
  53.             }  
  54.         };  
  55.         // 新建任務2,調用lockTest的getValue方法  
  56.         Runnable task2 = new Runnable(){  
  57.             public void run(){  
  58.                 System.out.println("value: " + lockTest.getValue());  
  59.             }  
  60.         };  
  61.         // 新建任務執行服務  
  62.         ExecutorService cachedService = Executors.newCachedThreadPool();  
  63.         Future future = null;  
  64.         // 同時執行任務1三次,由於addValue方法使用了鎖機制,所以,實質上會順序執行  
  65.         for (int i=0; i<3; i++){  
  66.             future = cachedService.submit(task1);  
  67.         }  
  68.         // 等待最后一個任務1被執行完  
  69.         future.get();  
  70.         // 再執行任務2,輸出結果  
  71.         future = cachedService.submit(task2);  
  72.         // 等待任務2執行完后,關閉任務執行服務  
  73.         future.get();  
  74.         cachedService.shutdownNow();  
  75.     }  
  76.       
  77.     /** 
  78.      * ReadWriteLock內置兩個Lock,一個是讀的Lock,一個是寫的Lock。 
  79.      * 多個線程可同時得到讀的Lock,但只有一個線程能得到寫的Lock, 
  80.      * 而且寫的Lock被鎖定后,任何線程都不能得到Lock。ReadWriteLock提供的方法有: 
  81.      * readLock(): 返回一個讀的lock  
  82.      * writeLock(): 返回一個寫的lock, 此lock是排他的。 
  83.      * ReadWriteLockTest很適合處理類似文件的讀寫操作。 
  84.      * 讀的時候可以同時讀,但不能寫;寫的時候既不能同時寫也不能讀。 
  85.      */  
  86.     public static class ReadWriteLockTest{  
  87.         // 鎖  
  88.         ReadWriteLock lock = new ReentrantReadWriteLock();  
  89.         // 值  
  90.         double value = 0d;  
  91.         int addtimes = 0;  
  92.           
  93.         /** 
  94.          * 增加value的值,不允許多個線程同時進入該方法 
  95.          */  
  96.         public void addValue(double v) {  
  97.             // 得到writeLock並鎖定  
  98.             Lock writeLock = lock.writeLock();  
  99.             writeLock.lock();  
  100.             System.out.println("ReadWriteLockTest to addValue: " + v + "   "  
  101.                     + System.currentTimeMillis());  
  102.             try {  
  103.                 Thread.sleep(1000);  
  104.             } catch (InterruptedException e) {  
  105.             }  
  106.             try {  
  107.                 // 做寫的工作  
  108.                 this.value += v;  
  109.                 this.addtimes++;  
  110.             } finally {  
  111.                 // 釋放writeLock鎖  
  112.                 writeLock.unlock();  
  113.             }  
  114.         }  
  115.         /** 
  116.          * 獲得信息。當有線程在調用addValue方法時,getInfo得到的信息可能是不正確的。 
  117.          * 所以,也必須保證該方法在被調用時,沒有方法在調用addValue方法。 
  118.          */  
  119.         public String getInfo() {  
  120.             // 得到readLock並鎖定  
  121.             Lock readLock = lock.readLock();  
  122.             readLock.lock();  
  123.             System.out.println("ReadWriteLockTest to getInfo   "  
  124.                     + System.currentTimeMillis());  
  125.             try {  
  126.                 Thread.sleep(1000);  
  127.             } catch (InterruptedException e) {  
  128.             }  
  129.             try {  
  130.                 // 做讀的工作  
  131.                 return this.value + " : " + this.addtimes;  
  132.             } finally {  
  133.                 // 釋放readLock  
  134.                 readLock.unlock();  
  135.             }  
  136.         }  
  137.     }  
  138.       
  139.     public static void testReadWriteLockTest() throws Exception{  
  140.         final ReadWriteLockTest readWriteLockTest = new ReadWriteLockTest();  
  141.         // 新建任務1,調用lockTest的addValue方法  
  142.         Runnable task_1 = new Runnable(){  
  143.             public void run(){  
  144.                 readWriteLockTest.addValue(55.55);  
  145.             }  
  146.         };  
  147.         // 新建任務2,調用lockTest的getValue方法  
  148.         Runnable task_2 = new Runnable(){  
  149.             public void run(){  
  150.                 System.out.println("info: " + readWriteLockTest.getInfo());  
  151.             }  
  152.         };  
  153.         // 新建任務執行服務  
  154.         ExecutorService cachedService_1 = Executors.newCachedThreadPool();  
  155.         Future future_1 = null;  
  156.         // 同時執行5個任務,其中前2個任務是task_1,后兩個任務是task_2  
  157.         for (int i=0; i<2; i++){  
  158.             future_1 = cachedService_1.submit(task_1);  
  159.         }  
  160.         for (int i=0; i<2; i++){  
  161.             future_1 = cachedService_1.submit(task_2);  
  162.         }  
  163.         // 最后一個任務是task_1  
  164.         future_1 = cachedService_1.submit(task_1);  
  165.         // 這5個任務的執行順序應該是:  
  166.         // 第一個task_1先執行,第二個task_1再執行;這是因為不能同時寫,所以必須等。  
  167.         // 然后2個task_2同時執行;這是因為在寫的時候,就不能讀,所以都等待寫結束,  
  168.         // 又因為可以同時讀,所以它們同時執行  
  169.         // 最后一個task_1再執行。這是因為在讀的時候,也不能寫,所以必須等待讀結束后,才能寫。  
  170.           
  171.         // 等待最后一個task_2被執行完  
  172.         future_1.get();  
  173.         cachedService_1.shutdownNow();  
  174.     }  
  175.   
  176.     public static void main(String[] args) throws Exception{  
  177.         Lockers.testLockTest();  
  178.         System.out.println("---------------------");  
  179.         Lockers.testReadWriteLockTest();  
  180.     }  
  181. }  
 
5


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM