多線程知識總結

多線程

創建線程的兩種方式
1.繼承Thread,覆蓋父類Run方法
2.實現Runable接口,重寫Run方法

多線程機制並沒有提高程序的運行效率,只是因爲開啓了多個線程,佔用了服務器更多的帶寬。

定時器
Timer 
TimerTask
new Timer().schedule(new TimerTask(){
    @override
    public void run(){
        
}


},多少秒後執行run,前面執行後每隔多少秒再執行一次run);

線程間的互斥與同步通信
1.方法簽名上添加Synchronized
2.需要同步的代碼封裝到Synchronized塊中
Synchronized(該同步塊所在類的字節碼對象){

}
經驗:
要用到共同數據(包括同步鎖)的若干個方法,都應該將這些方法歸在同一個類中,這種設計
符合高內聚,和程序的健壯性,便於維護。
經驗:
有些時候,線程會發生僞喚醒的情況,此時在同步塊內使用while(){}判斷,會比使用if更具有健壯性。
因爲if只會判斷一次,符合條件就進入。而while在循環結束後,還會判斷一次。
經驗:
代碼編寫過程中,某些運算符,本身包含邏輯的處理,如三元運算,本身就有true和false的判斷,
就不需要再使用邏輯判斷了。
還有if中,不需要再添加邏輯判斷。

ThreadLocal實現線程範圍的共享變量
變量 ThreadLocal<Integer> x = new ThreadLocal<>();
自定義類 ThreadLocal<MyObject> myObject = new ThreadLocal<>();

使用單例模式+單例類中,私有化一個靜態的ThreadLocal<單例類> = new ThreadLocal<>(),
將單例對象放入ThreadLocal中,每次獲取時,先判斷ThreadLocal中有沒有,有就取出,並返回,
沒有就new一個,存入ThreadLocal,並返回。
來保證數據在該單例中被共享。

全局的ThreadLocal變量中,當多個線程使用set方法往裏面存值後,就相當於往裏面的map存儲多條
記錄,key分別是各個線程的線程名。當線程結束時,ThreadLocal會自動將死亡的線程釋放。
可以調用ThreadLocal的clear方法,將線程全部清空。

多個線程訪問共享對象和數據的方式
1.如果每個線程執行的代碼相同,可以使用同一個Runnable對象,這個Runable中封裝共享數據,和對數據的操作。例如
買票系統。
2.如果每個系統執行的代碼不同,
    
2.1 將共享數據封裝到一個對象中,然後將對象通過實現Runnable接口對象的構造方法逐一傳遞給各個Runable對象,每個線程對
共享數據的操作方法也放到該對象中,這樣容易實現針對該數據進行的各個操作的互斥和通信。
   
 2.2 將這些Runnable對象作爲某一個類中的內部類,共享數據作爲這個外部類中的成員變量,
每個線程對共享數據的操作方法也分配給外部類。以便實現對共享數據進行的各個操作的互斥和通信,
作爲內部類的各個Runable對象調用外部類的這些方法。
    
2.3 將共享數據封裝到另一個對象中,每個線程對共享數據的操作方法也分配到那個對象中,對象作爲這個外部類
中的成員變量或方法中的局部變量,每個線程的Runable對象作爲外部類中的成員內部類或局部內部類。
(定義一個類,類中將共享數據定義爲成員變量,並提供對該變量的操作函數,函數使用synchronized修飾,再定義多個實現了Runnable接口
口的成員內部類,該成員內部類通過內部Run方法調用同一級別的對共享數據操作的成員方法)


java5提供了線程併發庫

java.util.concurrent包
automic  提供了對於基本數據類型,和類中基本數據類型的原子性操作。
AutomicInteger
java.utl.concurrent.atomic包

線程池ExecutorService threadPool = 
1.固定線程池 Executors.newFixedThreadPool(3);
2.緩存線程池 Executors.newCachedThreadPool();
3.單一線程池 Executors.newSingleThreadExecutor();(實現線程死掉後重新啓動 其實就是在線程死掉後,使用原有引用變量指向一個新的線程)
關閉線程池
shutdown 所有任務執行完後,關閉所有線程
shutdownNow 當前任務完成後,關閉所有線程
線程池任務調度:給線程池中線程分配任務。可以分配多個schedule()
Executors.newScheduledThreadPool(3).schedule(Runnable,delay,unit);



Callable&Future
 Future取得的結果類型必須與Callable返回的結果類型一致,通過泛型實現。
Callable採用ExecutorService的submit()方法提交,返回的future對象可以取消任務。 

Future<T> future = threadPool.submit(new Callable<T>(){
    public String call() throws Exception{
        //Thread.sleep(2000);
        return t.type = T;
}
});
future.get();

CompletionService 用於提交一組Callable任務,其take方法返回已完成的一個Callable任務對應的Futurure
對象。類似qq種菜機制,中下一波種子,優先成熟的可以收穫或偷取。

CompletionService<V> c = new ExecutorCompletionService<V>

Lock&Condition實現線程同步通信
Lock比傳統線程模型中的Synchronized方式更加面向對象,與生活中的鎖類似,鎖本身也應該是一個對象,
兩個線程執行的代碼片段要實現同步互斥的效果,它們必須用同一個Lock對象,鎖是在代表要操作的資源的
類的內部方法中,而不是線程代碼中

使用Lock注意事項
1.多個線程的lock對象必須一致.   
2.lock需要放在線程訪問的共享資源中。
Lock是一個接口
實現類有ReentrantLock  
方法
    lock.lock();

    try{
        需要鎖住的代碼
    
    }finally{
        //執行完成後,必須釋放鎖,不然可能會導致線程死在鎖住的代碼中,後續線程無法進入。
        lock.unlock();
}

讀寫鎖,限制代碼在執行過程中是否允許同步執行讀或寫的操作。
對讀寫方法中,具體執行讀寫操作的代碼上鎖
讀方法上讀鎖
寫方法上寫鎖

接口ReadWriteLock 
實現類 ReentrantReadWriteLock
    lock.readLock().lock();
        try{
            需要上讀鎖的代碼
           
    }finally{
             lock.readLock().unlock();
    }
    
    lock.writeLock().lock();
    
    try{

}finally{
    lock.writeLock.unlock();   
}

Lock可以替代Synchronize完成線程互斥
Condition可以替代Object.wait()和Object.notify()完成同步通信
Condition condition = lock.newCondition(); 
condition.await();
condition.signal();   

信號燈
Semaphore可以控制同時訪問資源的線程個數。例如:實現文件的併發訪問。
   
 Semaphore sp = new Semaphore(3);
acquire()獲得一個許可
release()釋放一個許可

Semaphore對象可以實現互斥鎖的功能,並且可以是由一個線程獲得了“鎖”,再由另一個線程釋放
“鎖”,這可應用於死鎖恢復的一些場合。

工具類
CyclicBarrier 彼此等待,集合後分散活動 ,分散活動後在指定地點集合,集合後再分散。
CountDownLatch 倒計時記時器 實現裁判吹口號,運動員起跑,運動員都到達終點後,開始評判成績。
Exchanger 用於實現兩個人之間的數據交換,每個人在完成一定的事務後想與對方交換數據,第一個先拿
出數據的人將一直等待第二個人拿着數據到來時,才能彼此交換數據。

阻塞隊列
接口BlockingQueue                                沒有值時報異常   沒有值時爲null    沒有值時阻塞,等待有值(無值)時,進行存取。
ArrayBlockingQueue    存值的方式有三種,add                   offer                 put                      put()   take()會產生阻塞
                                   取值的方式有三種 ,  remove             poll                   take   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章