concurrent包 線程池、資源封鎖和隊列、ReentrantReadWriteLock介紹

jdk1.5後,提供了java.util.concurrent包,它能夠實現線程池,你把線程當成普通對象就能夠了,它來負責調度和執行java

包括兩類線程池ui

固定線程池atom

可變線程池spa

延遲線程池線程

 

固定線程池對象

public static ExecutorService newFixedThreadPool(int nThreads)     多任務接口

public static ExecutorService newSingleThreadPool()   單任務隊列

ExecutorService 的方法進程

Excute(Runnablecommand);element

shutdown();

用法以下

Mytask mt1=new Mytask("T1");//一個線程對象實例

ExecutorService  threadpool=Executors.newFixedThreadPool(2);

threadpool.excute(mt1);

 

可變線程池

public static ExecutorService newCachedThreadPool()    

 

延遲線程池,實現定時任務

public static ScheduledExecutorService newScheduledThreadPool(int poolSize)   

它不使用excute方法了,而是使用schedule方法

public SchedualedFuture schedule(Runnable command,long delay,TimeUnit unit);

 

有返回值的線程池

Callable接口配合Future接口,Future接口用來接受返回值

Callable接口做用同runnable接口,不過它是實現call接口方法,這個方法還有返回值

class myCallableImpl implements Callable

{

public Object call()

{

}

}

使用

ExecutorService threadpool =Executors.newSingleThreadExector();

Future f=threadpool.submit(new myCallableImpl();

 

資源封鎖

前面咱們知道syncnized方法能夠對一段代碼進行資源封鎖,實際上還有不少其餘方法,這裏總結一下

1:synchronized

2:變量volatile

3:lock接口的實現 ReentrantLock類,它有方法:lock()、unlock(),tryLock()等,注意要try……finally,防止死鎖

4:ReadWriteLock接口實現 ReentrantReadWriteLock類,方法爲readLock,writeLock,使用方法大體同lock接口,不過它的效率高。也要防止死鎖

5:信號量 Semaphore類,信號量不一樣於鎖,是用來實現資源分配的,可是也有鎖的特性,好比鏈接池,保證鏈接池不爆炸就可使用這個類,主要方法爲:acquire(),acquire(int n),tryAcquire(),getQueueLength(),release()

6:原子對象,在jdk15後,爲了簡化操做,能夠把一些基本類型定義爲原子對象,就單線程操做了。java.util.concurrent.atomic ,做用基本同變量volatile

7:障礙器,CyclicBarrier類,讓線程同步到同一個點

 

隊列和堆棧

java.util.Queue接口

public boolean offer(Object);  加入

public Object poll();   出

peek();  出,可是不刪除

remove();同poll

element();同peek

add();同offer

常見實現爲:java.util.LinkedList  和 java.util.PriorityQueue

BlockingQueue接口

java.util.concurrent.BlockingQueue

put(Object);進

take();出

BlockingDeque接口

它是一個阻塞的堆棧接口

putFirst(object o);

takeFirst();

putLast();

takeLast();

ReentrantReadWriteLock介紹

在java中提供了ReentrantReadWriteLock類 ,並可抽取讀鎖和寫鎖。讀鎖能夠被多個讀操做共享,而且會排斥全部寫操做;寫鎖則互斥全部寫操做和讀操做。
使用讀/寫鎖的必要步驟:

class RWDictionary {
    private final Map   m = new TreeMap ();

    //1)建立ReentrantReadWriteLock對象
    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    private final Lock r = rwl.readLock();//2) 抽取讀鎖
    private final Lock w = rwl.writeLock();//2) 抽取寫鎖

    public Data get(String key) {

         3) 對全部讀者加鎖
        r.lock(); try { return m.get(key); } finally { r.unlock(); }
    }
    public String[] allKeys() {

        3 ) 對全部讀者加鎖
        r.lock(); try { return m.keySet().toArray(); } finally { r.unlock(); }
    }
    public Data put(String key, Data value) {

       4) 對全部寫者加鎖:
        w.lock(); try { return m.put(key, value); } finally { w.unlock(); }
    }
    public void clear() {

       4) 對全部寫者加鎖:
        w.lock(); try { m.clear(); } finally { w.unlock(); }
    }
}

這樣能夠保證   a) 寫者之間以及寫者和讀者之間互斥
                   b) 同一時間只有一個寫者寫,多個讀者能夠同時讀
這樣讀者和寫者的優先級相同,當有大量的讀者和極少的寫者時,寫進程可能很可貴到執行。因此當須要寫操做優先級更高時能夠設置ReentrantReadWriteLock 的策略,設置爲非公平策略便可

    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(false);

把構作ReentrantReadWriteLock設爲false(非公平策略)(默認爲true)

公平策略:當公平地構造線程時,線程利用一個近似到達順序的策略來爭奪進入。當釋放寫入鎖定後,將寫入鎖定分配給等待時間最長的單個寫入者,若是有一個等待時間比全部寫入者更長的讀取者,則將讀取鎖定分配給讀取者

非公平策略:當非公平地構造線程時,則不須要按照到達順序進入鎖定。無論是哪種狀況,若是讀取者處於活動狀態,而某個寫入者進入鎖定狀態,那麼在獲取寫入者並釋放寫入鎖定以前,不會將讀取鎖定授予任何後續的讀取者。

相關文章
相關標籤/搜索