新的起點 新的開始

          快樂生活 !

          (轉)Java 5.0多線程編程(3)

          Lock 接口

          ReentrantLock Lock 的具體類, Lock 提供了以下一些方法:

          • lock(): 請求鎖定,如果鎖已被別的線程鎖定,調用此方法的線程被阻斷進入等待狀態。
          • tryLock() :如果鎖沒被別的線程鎖定,進入鎖定狀態,并返回 true 。若鎖已被鎖定,返回 false ,不進入等待狀態。此方法還可帶時間參數,如果鎖在方法執行時已被鎖定,線程將繼續等待規定的時間,若還不行才返回 false
          • unlock() :取消鎖定,需要注意的是 Lock 不會自動取消,編程時必須手動解鎖。

          代碼:

          // 生成一個鎖

          Lock lock = new ReentrantLock();

          public void accessProtectedResource() {

          ? lock.lock(); // 取得鎖定

          ? try {

          ??? // 對共享資源進行操作

          ? } finally {

          ??? // 一定記著把鎖取消掉,鎖本身是不會自動解鎖的

          ??? lock.unlock();

          ? }

          }

          ReadWriteLock 接口

          ?? 為了提高效率有些共享資源允許同時進行多個讀的操作,但只允許一個寫的操作,比如一個文件,只要其內容不變可以讓多個線程同時讀,不必做排他的鎖定,排他的鎖定只有在寫的時候需要,以保證別的線程不會看到數據不完整的文件。 ReadWriteLock 可滿足這種需要。 ReadWriteLock 內置兩個 Lock ,一個是讀的 Lock ,一個是寫的 Lock 。多個線程可同時得到讀的 Lock ,但只有一個線程能得到寫的 Lock ,而且寫的 Lock 被鎖定后,任何線程都不能得到 Lock ReadWriteLock 提供的方法有:

          • readLock(): 返回一個讀的 lock
          • writeLock(): 返回一個寫的 lock, lock 是排他的。

          ReadWriteLock 的例子:

          public class FileOperator{

          ????? // 初始化一個 ReadWriteLock

          ????? ReadWriteLock lock = new ReentrantReadWriteLock();

          public String read() {

          ????? // 得到 readLock 并鎖定

          ??????????? Lock readLock = lock.readLock();

          ?????? ?????readLock.lock();

          ??????????? try {

          ????????????????? // 做讀的工作

          ????????????????? return "Read something";

          ??????????? } finally {

          ???????????????? readLock.unlock();

          ??????????? }

          ????? }

          ?????

          public void write(String content) {

          ????? // 得到 writeLock 并鎖定

          ??????????? Lock writeLock = lock.writeLock();

          ??????????? writeLock.lock();

          ??????????? try {

          ????????????????? // 做讀的工作

          ??????????? } finally {

          ???????????????? writeLock.unlock();

          ??????????? }

          ????? }

          }

          ?

          ?? 需要注意的是 ReadWriteLock 提供了一個高效的鎖定機理,但最終程序的運行效率是和程序的設計息息相關的,比如說如果讀的線程和寫的線程同時在等待,要考慮是先發放讀的 lock 還是先發放寫的 lock 。如果寫發生的頻率不高,而且快,可以考慮先給寫的 lock 。還要考慮的問題是如果一個寫正在等待讀完成,此時一個新的讀進來,是否要給這個新的讀發鎖,如果發了,可能導致寫的線程等很久。等等此類問題在編程時都要給予充分的考慮。

          Condition 接口:

          ?? 有時候線程取得 lock 后需要在一定條件下才能做某些工作,比如說經典的 Producer Consumer 問題, Consumer 必須在籃子里有蘋果的時候才能吃蘋果,否則它必須暫時放棄對籃子的鎖定,等到 Producer 往籃子里放了蘋果后再去拿來吃。而 Producer 必須等到籃子空了才能往里放蘋果,否則它也需要暫時解鎖等 Consumer 把蘋果吃了才能往籃子里放蘋果。在 Java 5.0 以前,這種功能是由 Object 類的 wait(), notify() notifyAll() 等方法實現的,在 5.0 里面,這些功能集中到了 Condition 這個接口來實現, Condition 提供以下方法:

          • await() :使調用此方法的線程放棄鎖定,進入睡眠直到被打斷或被喚醒。
          • signal(): 喚醒一個等待的線程
          • signalAll() :喚醒所有等待的線程

          Condition 的例子:

          public class Basket {?????

          Lock lock = new ReentrantLock();

          // 產生 Condition 對象

          ???? Condition produced = lock.newCondition();

          ???? Condition consumed = lock.newCondition();

          ???? boolean available = false;

          ?? ??

          ???? public void produce() throws InterruptedException {

          ?????????? lock.lock();

          ?????????? try {

          ???????????????? if(available){

          ??????????????????? consumed.await(); // 放棄 lock 進入睡眠 ?

          ???????????????? }

          ???????????????? /* 生產蘋果 */

          ???????????????? System.out.println("Apple produced.");

          ???????????????? available = true;

          ???????????????? produced.signal(); // 發信號喚醒等待這個 Condition 的線程

          ?????????? } finally {

          ???????????????? lock.unlock();

          ?????????? }

          ???? }

          ????

          ???? public void consume() throws InterruptedException {

          ?????????? lock.lock();

          ?????????? try {

          ???????????????? if(!available){

          ?????????????????????? produced.await();// 放棄 lock 進入睡眠 ?

          ???????????????? }

          ???????????????? /* 吃蘋果 */

          ???????????????? System.out.println("Apple consumed.");

          ???????????????? available = false;

          ???????????????? consumed.signal();// 發信號喚醒等待這個 Condition 的線程

          ?????????? } finally {

          ???????????????? lock.unlock();

          ?????????? }

          ???? }?????

          }

          ConditionTester:

          public class ConditionTester {

          ?????

          ????? public static void main(String[] args) throws InterruptedException{

          final Basket basket = new Basket();

          // 定義一個 producer

          ??????????? Runnable producer = new Runnable() {

          ????????????????? public void run() {

          ??????????????????????? try {

          ????????????????????????????? basket.produce();

          ?????? ?????????????????} catch (InterruptedException ex) {

          ????????????????????????????? ex.printStackTrace();

          ??????????????????????? }

          ????????????????? }

          };

          // 定義一個 consumer

          ??????????? Runnable consumer = new Runnable() {

          ????????????????? public void run() {

          ??????????????????????? try {

          ????????????????????????????? basket.consume();

          ??????????????????????? } catch (InterruptedException ex) {

          ????????????????????????????? ex.printStackTrace();

          ??????????????????????? }

          ????????????????? }

          };

          // 各產生 10 consumer producer

          ??????????? ExecutorService service = Executors.newCachedThreadPool();

          ??????????? for(int i=0; i < 10; i++)

          ????????????????? service.submit(consumer);

          ??????????? Thread.sleep(2000);

          ??????????? for(int i=0; i<10; i++)

          ????????????????? service.submit(producer);

          ??????????? service.shutdown();

          ????? }?????

          }

          5: Synchronizer:同步裝置

          ?? Java 5.0 里新加了 4 個協調線程間進程的同步裝置,它們分別是 Semaphore, CountDownLatch, CyclicBarrier Exchanger.

          Semaphore:

          ?? 用來管理一個資源池的工具, Semaphore 可以看成是個通行證,線程要想從資源池拿到資源必須先拿到通行證, Semaphore 提供的通行證數量和資源池的大小一致。如果線程暫時拿不到通行證,線程就會被阻斷進入等待狀態。以下是一個例子:

          public class Pool {

          ??? ??ArrayList pool = null;

          ????? Semaphore pass = null;

          ????? public Pool(int size){

          ??????????? // 初始化資源池

          ??????????? pool = new ArrayList();

          ??????????? for(int i=0; i

          ????????????????? pool.add("Resource "+i);

          ??????????? }

          ??? ????????//Semaphore 的大小和資源池的大小一致

          ??????????? pass = new Semaphore(size);

          ????? }

          ????? public String get() throws InterruptedException{

          ??????????? // 獲取通行證 , 只有得到通行證后才能得到資源

          ??????????? pass.acquire();

          ??????????? return getResource();

          ????? }

          ????? public void put(String resource){

          ??????????? // 歸還通行證,并歸還資源

          ??????????? pass.release();

          ??????????? releaseResource(resource);

          ????? }

          ???? private synchronized String getResource() {

          ??????????? String result = pool.get(0);

          ??????????? pool.remove(0);

          ??????????? System.out.println("Give out "+result);

          ??????????? return result;

          ????? }

          ????? private synchronized void releaseResource(String resource) {

          ??????????? System.out.println("return "+resource);

          ??????????? pool.add(resource);

          ????? }

          }

          SemaphoreTest:

          public class SemaphoreTest {

          ????? public static void main(String[] args){

          ??????????? final Pool aPool = new Pool(2);

          ??????????? Runnable worker = new Runnable() {

          ????????????????? public void run() {

          ??????????????????????? String resource = null;

          ??????? ????????????????try {

          ????????????????????????????? // 取得 resource

          ????????????????????????????? resource = aPool.get();

          ??????????????????????? } catch (InterruptedException ex) {

          ????????????????????????????? ex.printStackTrace();

          ??????????????????????? }

          ??????????????????????? // resource 做工作

          ??????????????????????? System.out.println("I worked on "+resource);

          ??????????????????????? // 歸還 resource

          ??????????????????????? aPool.put(resource);

          ????????????????? }

          ??????????? };

          ??????????? ExecutorService service = Executors.newCachedThreadPool();

          ??????????? for(int i=0; i<20; i++){

          ????????????????? service.submit(worker);

          ??????????? }

          ??????????? service.shutdown();

          ????? }????

          }


          posted on 2007-03-26 14:31 advincenting 閱讀(257) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          公告

          Locations of visitors to this pageBlogJava
        1. 首頁
        2. 新隨筆
        3. 聯系
        4. 聚合
        5. 管理
        6. <2007年3月>
          25262728123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          統計

          常用鏈接

          留言簿(13)

          隨筆分類(71)

          隨筆檔案(179)

          文章檔案(13)

          新聞分類

          IT人的英語學習網站

          JAVA站點

          優秀個人博客鏈接

          官網學習站點

          生活工作站點

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 探索| 平潭县| 托克托县| 阿荣旗| 台南县| 高密市| 响水县| 绥宁县| 定安县| 无极县| 汉沽区| 乌什县| 溆浦县| 沂水县| 耿马| 工布江达县| 江城| 嘉义县| 泸溪县| 乐平市| 昌吉市| 治县。| 东辽县| 桃源县| 长白| 油尖旺区| 施秉县| 金平| 广灵县| 邵阳县| 陇川县| 莎车县| 印江| 尼勒克县| 鄂托克前旗| 巴南区| 博爱县| 沙洋县| 华安县| 吕梁市| 贺兰县|