5: Synchronizer:同步裝置
Java 5.0里新加了4個(gè)協(xié)調(diào)線程間進(jìn)程的同步裝置,它們分別是Semaphore, CountDownLatch, CyclicBarrier和Exchanger.
Semaphore:
用來(lái)管理一個(gè)資源池的工具,Semaphore可以看成是個(gè)通行證,線程要想從資源池拿到資源必須先拿到通行證,Semaphore提供的通行證數(shù)量和資源池的大小一致。如果線程暫時(shí)拿不到通行證,線程就會(huì)被阻斷進(jìn)入等待狀態(tài)。以下是一個(gè)例子:
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();
}
}
CountDownLatch:
CountDownLatch是個(gè)計(jì)數(shù)器,它有一個(gè)初始數(shù),等待這個(gè)計(jì)數(shù)器的線程必須等到計(jì)數(shù)器倒數(shù)到零時(shí)才可繼續(xù)。比如說(shuō)一個(gè)Server啟動(dòng)時(shí)需要初始化4個(gè)部件,Server可以同時(shí)啟動(dòng)4個(gè)線程去初始化這4個(gè)部件,然后調(diào)用CountDownLatch(4).await()阻斷進(jìn)入等待,每個(gè)線程完成任務(wù)后會(huì)調(diào)用一次CountDownLatch.countDown()來(lái)倒計(jì)數(shù), 當(dāng)4個(gè)線程都結(jié)束時(shí)CountDownLatch的計(jì)數(shù)就會(huì)降低為0,此時(shí)Server就會(huì)被喚醒繼續(xù)下一步操作。CountDownLatch的方法主要有:
await():使調(diào)用此方法的線程阻斷進(jìn)入等待
countDown(): 倒計(jì)數(shù),將計(jì)數(shù)值減1
getCount(): 得到當(dāng)前的計(jì)數(shù)值
CountDownLatch的例子:一個(gè)server調(diào)了三個(gè)ComponentThread分別去啟動(dòng)三個(gè)組件,然后server等到組件都啟動(dòng)了再繼續(xù)。
public class Server {
public static void main(String[] args) throws InterruptedException{
System.out.println("Server is starting.");
//初始化一個(gè)初始值為3的CountDownLatch
CountDownLatch latch = new CountDownLatch(3);
//起3個(gè)線程分別去啟動(dòng)3個(gè)組件
ExecutorService service = Executors.newCachedThreadPool();
service.submit(new ComponentThread(latch, 1));
service.submit(new ComponentThread(latch, 2));
service.submit(new ComponentThread(latch, 3));
service.shutdown();
//進(jìn)入等待狀態(tài)
latch.await();
//當(dāng)所需的三個(gè)組件都完成時(shí),Server就可繼續(xù)了
System.out.println("Server is up!");
}
}
public class ComponentThread implements Runnable{
CountDownLatch latch;
int ID;
/** Creates a new instance of ComponentThread */
public ComponentThread(CountDownLatch latch, int ID) {
this.latch = latch;
this.ID = ID;
}
public void run() {
System.out.println("Component "+ID + " initialized!");
//將計(jì)數(shù)減一
latch.countDown();
}
}
運(yùn)行結(jié)果:
CyclicBarrier:
CyclicBarrier類似于CountDownLatch也是個(gè)計(jì)數(shù)器,不同的是CyclicBarrier數(shù)的是調(diào)用了CyclicBarrier.await()進(jìn)入等待的線程數(shù),當(dāng)線程數(shù)達(dá)到了CyclicBarrier初始時(shí)規(guī)定的數(shù)目時(shí),所有進(jìn)入等待狀態(tài)的線程被喚醒并繼續(xù)。CyclicBarrier就象它名字的意思一樣,可看成是個(gè)障礙,所有的線程必須到齊后才能一起通過(guò)這個(gè)障礙。CyclicBarrier初始時(shí)還可帶一個(gè)Runnable的參數(shù),此Runnable任務(wù)在CyclicBarrier的數(shù)目達(dá)到后,所有其它線程被喚醒前被執(zhí)行。
相關(guān)推薦:計(jì)算機(jī)等級(jí)考試二級(jí)Java經(jīng)典算法大全匯總北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |