Java併發核心-semaphore

Java併發核心-semaphore

Semaphore 是 synchronized 的增強版,做用是控制線程的併發數量。

  1. semaphore
package com.f.fmodules.fuser.semaphore;


public class MyThread extends Thread {

    private SemaphoreService service;

    public MyThread(String name, SemaphoreService service) {
        super();
        this.setName(name);
        this.service = service;
    }

    @Override
    public void run() {
        this.service.doSomething();
    }
}
package com.f.fmodules.fuser.semaphore;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Semaphore;

public class SemaphoreService {

    private static SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

    /**同步關鍵類,構造方法傳入的數字是多少,則同一個時刻,只運行多少個進程同時運行制定代碼*/
    private Semaphore semaphore = new Semaphore(3);

    /**
     * 在 semaphore.acquire() 和 semaphore.release()之間的代碼,同一時刻只容許制定個數的線程進入,
     * 由於semaphore的構造方法是1,則同一時刻只容許一個線程進入,其餘線程只能等待。
     * */
    public void doSomething() {
        try {
            semaphore.acquire();
            System.out.println(Thread.currentThread().getName() + ":doSomething start-" + getFormatTimeStr());
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() + ":doSomething end-" + getFormatTimeStr());
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static String getFormatTimeStr() {
        return sf.format(new Date());
    }
}
package com.f.fmodules.fuser.semaphore;

public class SemaphoreTest {
    public static void main(String args[]) {
        SemaphoreService service = new SemaphoreService();
        for (int i = 0; i < 10; i++) {
            MyThread t = new MyThread("thread" + (i + 1), service);
            t.start();// 這裏使用 t.run() 也能夠運行,可是不是併發執行了
        }
    }
}
  • 運行結果java

  • 實踐證實,確實是同一個時刻只有一個線程能訪問,那若是把 Semaphore 的構造方法入參改爲 5併發

  1. 方法 acquire( int permits ) 參數做用,及動態添加 permits 許可數量
  • acquire( int permits ) 中的參數是什麼意思呢?能夠這麼理解, new Semaphore(6) 表示初始化了 6個通路, semaphore.acquire(2) 表示每次線程進入將會佔用2個通路,semaphore.release(2) 運行時表示歸還2個通路。沒有通路,則線程就沒法進入代碼塊。
    而上面的代碼中,semaphore.acquire() + semaphore.release() 在運行的時候,其實和 semaphore.acquire(1) + semaphore.release(1) 效果是同樣的
  1. acquire 的不可中斷實現
  • 仔細看一下上面的代碼,semaphore.acquire() 和 semaphore.acquire(int permits) 是會拋出異常 InterruptedException 的,若是在 acquire 和 release 之間的代碼是一個比較慢和複製的運算,如內存佔用過多,或者棧深度很深等,jvm會中斷這塊代碼 如何才能不讓 jvm 中斷 代碼執行呢? 答案是:使用 acquireUninterruptibly() 替換acquire()、使用 acquireUninterruptibly(int permits) 替換 acquire(int permits)
相關文章
相關標籤/搜索