多線程學習總結

1.    

    創建線程的兩種方式 new 一個 繼承了Thread的類或者實現Runnable接口的類的對象作爲參數傳給Thread類的構造方法。

    isAlive() 的功能是判斷當前的線程是否處於活動狀態。(活動狀態就是線程已經啓動且尚未終止,線程處於正在運行或者準備開始運行的狀態,就認爲線程是
    存活的)
    
     sleep(long) long是毫秒數,指讓this.currentThread()休眠long毫秒,不釋放鎖。

    getId()作用是取得線程的唯一標識

1.停止線程的方式:

    方式一:interrupt()

    實際上沒有正真的停止,而是將線程標記爲停止,然後通過拋出異常的方式結束線程

    包括(先sleep()然後interrupt() 或者先interrupt()然後sleep() 均會拋出 

java.lang.InterruptedException:sleep interrupted

    this.interrupted():測試當前線程是否已經中斷(指的是運行interrupted方法的那個線程,並且該方法有清除中斷狀態的作用)。

    this.isInterrupted():測試線程是否已經中斷。

        以上兩個方法是判斷線程有沒有調用interrupt()方法。
    

    方式二:stop() 
        
        該方式是非常暴力的。在JDK中被標明是“作廢/過期”,不建議使用

    方式三:interrupt()與return結合,不如方式一,return 太多污染代碼嚴重

2.暫停線程

    suspend()線程暫停 resume()線程恢復

    Thread.yield()是放棄當前的CPU資源,將它讓給其他的任務去佔用CPU執行時間。但放棄的時間不確定,有可能剛剛放棄,又馬上獲得。    

3.線程優先級

    setPriority();getPriority(); 線程優先級具有繼承性,這個繼承指的是(比如A線程啓動B線

程,那麼B線程繼承A線程的優先級)

4.守護線程  

 
  典型的守護線程垃圾回收線程 將一個線程設置爲守護線程是用線程的setDaemon(true)方法


二 

1.同步鎖synchronized 是對象鎖,亦synchronized鎖的是對象,是排隊運行的。只有共享資源的讀

  寫訪問才需要同步化(多個線程訪問同一個實例/對象)
    
  線程A先持有object對象鎖,不影響線程B異步調用object非synchronized類型的方法,如果調用的是

  object對象中synchronized類型的方法,需等待lock鎖釋放,也就是同步。
    

2 髒讀: 讀取實例變量時,數據出現交叉,此值已經被其他線程更改過了。

3 synchronized 鎖重入 當一個線程得到一個對象鎖後,再次請求此對象鎖是還可以得到該鎖。

    可重入鎖也支持在父子類繼承的環境中,子類可以通過“可重入鎖”調用父類的同步方法。
    
4 出現異常,鎖自動釋放

5 同步不具有繼承性,解決方案:在子類中添加synchronized

6 synchronized方法是對當前對象加鎖,而synchronized代碼塊是對某一個對象進行加鎖。

7 synchronized 使用的是“對象監視器”是一個,synchronized(this)代碼塊也是鎖定當前對象的。

  多個線程調用同一個對象中的不同名稱的synchronized同步方法或synchronized(this)同步代碼塊時

,調用的效果就是順序執行,也就是同步的,阻塞的。

8 synchronized 同步方法對象鎖實際上就是this。非this對象鎖,鎖定同步代碼塊,就是與同步方法異

步,不與其他同步方法爭鎖,可大大提高效率。

9 synchronized  當多個線程執行 x 對象的synchronized 方法,x對象方法裏的synchronized(this)以

及synchronized(x)均同步

10 類鎖 synchronized 加到static 方法上,類鎖對所有對象實例起作用,也就是說,只要是該類的對象,

多個對象之間調用該類的任意 synchronized static 方法時同步。synchronized(class) 代碼塊的作用與

synchronized static 方法的作用一樣。並且synchronized static 與 synchronized(class) 都是用的同

一把鎖,就是該類的類對象(比如 A.java 類 那麼該鎖就是A.class)

11 String 常量池的特性

    String a= "a";實際上是從常量池中取得的a 對象,好比是枚舉,String a = new String("a");

是新建的a 對象,不是常量池中的那個a 對象。對於對象測試結果是 Object obj1 = new Object();

Object obj2 = new Object(); 

12 內置類
    
    其他類(非子類)想要調用非靜態內部類的構造方法首先要創建外部類對象,比如A類裏面包含B類 A

 那麼main 方法調用B類構造方法 B b =new A().new B(); 調用靜態內部類構造方法可以直接調用

B b = new B();

13 鎖對象的改變,對象鎖有可能被其他線程改變,當一個線程運行到synchronized時候這個鎖對象是什麼,

就爭奪什麼,即使在等待的過程中鎖對象發生了改變,這個線程等待的那把鎖還是之前的對象。

對於同一個對象,即使對象屬性被改變,運行結果還是同步,因爲鎖對象沒有改變。


14 volatile 解決私有堆棧中的值和公共堆棧中的值不同步。強制性從公共堆棧中進行取值。
 
使用volatile 關鍵字增加了實例變量在多個線程之間的可見性。最致命的缺點就是不支持原子性

線程安全包含原子性和可見性兩個方面,Java的同步機制都是圍繞這兩個方面來確保線程安全的。
 
  

15 JAVA 多線程--線程安全之原子性,有序性和可見性

原子性 : 操作是不可分的,比如a++;是 讀取a 的值,a的值加1,然後賦給a,或者說同步性

可見性 : 關鍵字volatile 可以理解成直接操作主內存,這就涉及到java的happens-before關係了

有序性 :有序性是指程序在執行的時候,程序的代碼執行順序和語句的順序是一致的。

在Java內存模型中,允許編譯器和處理器對指令進行重排序,但是重排序過程不會影響到單線程程序的執行,

卻會影響到多線程併發執行的正確性。

16 原子類import java.util.concurrent.atomic.AtomicInteger; 不用同步就能保證線程安全,原子類

也並不完全安全

synchronized 代碼塊有volatile同步功能 關鍵字 synchronized可以使多個線程訪問同一個資源具有同步性,

而且它還具有將線程工作內存中的私有變量與公共內存中的變量同步的功能。包含兩個特性:互斥性和可見性

同步synchronized不僅可以解決一個線程看到對象處於不一致狀態,還可以保證進入同步方法或者代碼塊的每個

線程,都看到由同一個鎖保護之前所有的修改效果。

三 線程間通信(大大提高CPU利用率)

    1  wait(),notify() 均在同步方法或者同步代碼塊中使用,(使用是鎖對象.方法)。如果線程沒有持有該對象的對象級別鎖,會拋出

IllegalMonitorStateException,它是RuntimeException的一個子類,因此不需要try-catch捕獲。在調用wait()

方法後,當前線程釋放鎖,代碼停止執行,直到被喚醒。在執行notify() 方法後,當前線程不是馬上釋放該對象鎖,

呈wait() 狀態的線程也並不能馬上獲取對象鎖,要等到執行notify()方法的線程將程序執行完,也就是退出

synchronized代碼塊後,當前線程纔會釋放鎖。當第一個獲得該對象鎖的wait線程運行完畢後,它會釋放掉該對象鎖,

此時如果該對象沒再次使用notify語句,其它等待的線程也不會獲得鎖,直到該對象發出notify或者notifyAll。

如果發出notify操作時沒有處於阻塞狀態中線程,那麼該命令會被忽略。

wait()方法可以使調用該方法的線程釋放共享資源的鎖,然後從運行狀態退出,進入等待隊列,直到被再次喚醒。

notify()方法喚醒其中等待同一共享資源的“一個”線程。
    
notifyAll()方法喚醒等待隊列中等待同一共享資源的所有線程。優先級最高的那個線程最先執行,但也有可能

隨機執行。
    
2  線程進入Runnable狀態大體分爲如下5種情況(可運行狀態)

調用sleep() 方法後經過的時間超過了指定的休眠時間

線程調用的阻塞IO已經返回,阻塞方法執行完畢。

線程成功獲得了試圖同步的監視器

線程正在等待某個通知,其他線程發出了通知

處於掛起狀態的線程調用了 resume恢復方法。

3  Blocked阻塞狀態

線程調用sleep方法。

線程調用了阻塞式IO方法,在該方法返回前,該線程被阻塞

同步監視器正在被其他線程所持有

線程等待某個通知

程序調用了suspend方法將該線程掛起。此方法容易導致死鎖,儘量避免使用該方法。

run()方法運行結束後進入銷燬階段,整個線程執行完畢。
    
每個鎖對象都有兩個隊列,一個是就緒隊列,一個是阻塞隊列。
    
3  當方法wait()被執行後,鎖被自動釋放,但是執行完notify()方法,鎖卻不自動釋放,當程序執行完同步代碼

塊釋放所在資源(sleep()線程進入阻塞,但是不釋放鎖對象)

4  當線程呈wait()狀態時,調用線程對象的interrupt()方法會出現InterruptedException

5  執行完同步代碼塊就會釋放對象鎖 

 在執行同步代碼塊的過程中,遇到異常而導致線程終止,鎖也會被釋放

在執行同步代碼塊的過程中,執行了鎖所屬對象的 wait()方法,這個線程會釋放對象鎖,而此線程對象會進入線程等待

池中。

6  使用notify()一次只隨機通知一個線程進行喚醒。

7 wait(long) 等待某一時間內是否有線程對鎖進行喚醒,如果沒有,long毫秒後自動喚醒。當然也可以在long毫秒之內被

其他線程喚醒。

8 通知過早,則會打亂程序正常的運行邏輯。在使用wait/notify 模式時,還要注意另外一種情況,也就是wait等待條件發

生了變化,也容易造成程序邏輯的混亂。

9 生產者,消費者模式,就是一個線程生產一個線程等待,有產品生產線程等待消費線程消費完通知生產線程生產,

沒有產品消費等待生產線程生產完通知消費線程消費。(一生產一消費)

多生產-多消費使用notify 造成假死,原因是連續喚醒同類。解決方法就是喚醒所有等待線程。if語句 改while;


java.lang.ThreadGroup.enumerate(Thread[] list) 方法複製該線程組及其子組中的所有活動線程到指定的數組。
java.lang.Thread.activeCount() 活動線程的當前線程的線程組中的數量


線程狀態 調用wait()  Thread.getState() WAITING  正常的RUNNABLE

10 操作棧:一生產一消費(if-notify);一生產多消費,多生產一消費,多生產多消費(while-notifyAll)


11,管道流(pipeStream)是一種特殊的流,用於在不同線程間直接傳遞數據。在JDK中提供了4個類來使線程間可以通信

 PipedInputStream 和 PipedOutputStream; PipedReader 和 PipedWriter、

對輸入流只能進行讀操作,對輸出流只能進行寫操作,程序中需要根據待傳輸數據的不同特性而使用不同的流

13 join()遇到interrupt()方法,則會出現InterruptedException異常

14 join(long)設定的毫秒數,如果調用join的那個線程對象執行完,join所在線程立刻被喚醒,不會等待long時間在喚醒;

(自己理解:就是說在調用join的那個方法執行完會喚醒此線程,同時開了一個定時器線程,long毫秒後也會喚醒此線程)

15 join(long) 與 sleep(long) 的區別

方法join(long)具有釋放鎖的特點,方法sleep(long) 不釋放鎖。wait(0)與wait()方法的實際意義是一樣的,都表示在沒有

喚醒的情況下該線程一直處於等待狀態。

16. 當線程遇到join()方法所有與join方法共同爭搶鎖的線程都要執行完,該線程才能再次獲得鎖執行下邊的代碼。

17.類ThreadLocal解決每個線程綁定自己的值。可以將ThreadLocal類比喻成全局存放數據的盒子。盒子中可以存儲每個線程的私有數據

  set(),get()方法使用 多個線程向ThreadLocal對象裏面set值,但是他們各自取得值還是各自的,相互不影響,好像是隔離的。

  ThreadLocal 對象沒有set()時,get()==null; 也可以繼承ThreadLocal類重寫initialValue()方法,給對象賦默認值。主線程與子線程
    
  獲取的值不一定相同,比如返回 new Date() 這個值調用get()方法產生的,不同的線程不同(自己理解:因爲對象不同)

  類InheritableThreadLocal 可以讓子線程繼承父線程的值。(就是被啓動的線程的 該類及其子類的對象的get()方法獲得的值繼承啓動

  該線程所屬的線程的值)繼承的同時還可以對值進一步處理。

    public class InheritableThread extends InheritableThreadLocal{
        
        @Override
        protected Object initialValue(){

            return new Date().getTime();
        }
        
        protectedObject childValue(Object parentValue){
            
            return parentValue+"我在子線程加的~!";
        }
        
    }

  值得注意的:在使用InheritableThreadLocal類需要注意,如果子線程在取值的同時,主線程將InheritableThreadLocal中的值進行更改

 那麼子線程取到的值還是舊值。
    
四  LOCK 的使用

    1.  ReentrantLock 類的使用

    ReentrantReadWriteLock 類                                            

    Condition 類的使用比wait()和notify()/notifyAll() 更靈活。使用notify()/notifyAll()方法進行通知時,被通知的線程卻是由JVM
    
    隨機選擇的。Condition可以實現前面介紹的"選擇性通知"。而synchronized相當於整個Lock對象只有一個單一的Condition對象,所有的
    
    線程都註冊在它一個對象的身上。線程開始notifyAll()時,需要通知所有WAITING線程,    沒有選擇權,會出現相當大的效率問題。

    使用ReentrantLock對象可以喚醒指定種類的線程,這是控制部分線程行爲的方便方式。

    公平鎖與非公平鎖,公平鎖表示線程獲取鎖的順序時按照線程加鎖的順序來分配的,即先來先得的FIFO先進先出順序。

    公平鎖創建 ReentrantLock lock = new ReentrantLock(true);非公平鎖  ReentrantLock lock = new ReentrantLock(false);

    公平鎖也只能保證基本有序,

 2. 方法 getHoldCount()、getQueueLength()和getWaitQueueLength()的測試  

     lock.getHoldCount() 鎖定的線程個數,也就是調用lock()方法的次數。

     getQueueLength()  等待獲取鎖的線程的個數

     getWaitQueueLength(Condition condition) 作用返回等待此鎖定相關的給定條件Condition的線程估計數。比如5個線程,每個線程

     都執行了同一個condition對象的await()方法,則調用getWaitQueueLength(Condition condition)方法返回的int值是5.

 3  方法 hasQueuedThread()、hasQueuedThreads()和hasWaiters()

      boolean hasQueuedThread(Thread thread)的作用時查詢指定的線程是否在等待獲取此鎖定
    
      boolean hasQueuedThreads()的作用時查詢是否有線程正在等待獲取此鎖定

      boolean hasWaiters(Condition condition) 的作用是查詢是否有線程正在等待與此鎖有關的condition條件。

      boolean isFair() 的作用是判斷是不是公平鎖

      boolean isHeldByCurrentThread()的作用是查詢當前線程是否保持此鎖定。
 
      boolean isLocked()的作用是查詢此鎖定是否由任意線程保持。
    
      void lockInterruptibly()作用是:如果當前線程未被中斷,則獲取鎖定,如果已經被中斷則出現異常。 

      boolean tryLock()的作用是,僅在調用時鎖定未被另一個線程保持的情況下,才獲取該鎖定。

      boolean tryLock(long timeout, TimeUnit unit) 的作用是,如果鎖定在給定等待時間內沒有被另一個線程保持,

      且當前線程未被中斷,則獲取該鎖定。TimeUnit時間單位。

      awaitUninterruptibly()與 await()相似,但是前者在遇到interrupt()方法時不拋異常,而後者拋出InterruptedException

      awaitUntil(Date) 等待多少時間後自動喚醒,當然也可以被其他線程喚醒。
    
  4   類ReentrantReadWriteLock 讀寫鎖,一個是讀操作相關的鎖,也稱共享鎖;另一個是寫操作相關的鎖,也稱排它鎖。在沒有線程Thread

      進行寫操作時,進行讀取操作的多個Thread都可以獲取讀鎖,而進行寫入操作的Thread只有在獲取寫鎖後才能進行寫入操作。即多個

      Thread 可以同時進行讀取操作,但是同一時刻只允許一個Thread進行寫入操作。 該類對象的兩個方法 lock.readLock().lock()與
    
      lock.writeLock().lock(); "讀寫"、"寫讀"、"寫寫"都是互斥的;而“讀讀”是異步的,非互斥。即只要出現寫操作就是互斥的。

五  定時器

    Timer 類的主要作用就是設置計劃任務,封裝任務的類卻是TimerTask是一個抽象類。Timer是個抽象類

    Timer的schedule(TimerTask task,Date time) 該方法的作用是在指定的日期執行一次某一個任務。

 1. 執行任務的時間晚於當前時間--在未來執行的效果。Calendar的add(),比如ca.add(Calendar.SECOND, 10)就是當前時間加10後的那個時間。

    new Timer()會一直運行 new Timer(true)時守護線程,TimerTask任務來不及執行。
    
    如果執行任務的時間早於當前時間,則立即執行task任務。
    
    Timer 中允許有多個TimerTask任務及延時。

2.  對於同一個Timer對象TimerTask是以隊列的方式一個一個被順序執行,所以執行的時間有可能和預期的時候不一致,因爲前面的任務有可能消耗的時間較長,後面

    的任務運行的時間也被延後。

3.  方法schedule(TimerTask task,Date firstTime, long period) 作用是在指定的間隔週期,無限循環地執行某一個任務。

4.   TimerTask類中的cancel()方法的作用是將自身從任務隊列中進行清除。

5.   TimerTask類的cancel()方法的作用是將自身從任務隊列中進行清除。 Timer類的cancel()方法是將任務隊列中的方法全部清除。Timer的cancel()方法有時並

     一定會停止計劃任務,而是正常執行。 原因是Timer類中的cancel()方法有時並沒有爭搶到queue鎖,則讓TimerTask類中的任務正常執行。

6.  schedule(TimerTask task,long delay)  在當前時間之後 delay 毫秒數後執行一次TimerTask任務。

    schedule(TimerTask task,long delay, long period)方法當前的時間爲參考時間,在此時間基礎上延遲指定毫秒數,再以某一間隔時間無限次數地執行某一個

    任務。凡是使用方法中帶有period參數的,都是無限循環執行TimerTask中地任務。

7. 方法scheduleAtFixedRate(TimerTask task, Date firstTime,long period); schedule 和 scheduleAtFixedRate都是順序執行,所以不要考慮非線程安全的情況

   主要區別只在於有沒有追趕特性。就是兩個時間段內的時間所對應的Task任務被"補充性"的執行。就是如果計劃執行時間早於當前時間,那麼該方法快速執行多次任

   務補充這段時間空缺。

六  單例模式與多線程

     1.使用DCL 雙檢查鎖機制解決多線程的延遲加載單例設計模式。或者使用靜態內部類解決此問題,但是靜態內置類可以達到線程安全問題,但如果遇到序列化對象時

    ,使用默認的方式運行得到的結果還是多例的。

     序列化對象解決辦法就是在反序列化中使用readResolve()方法。

    public class MyObject implements Serializable{
    
        private static final long serialVersionUID = 888L;
    
        private static class MyObjectHandler{
        private static final MyObject myObject = new MyObject();
        };
    
        private MyObject(){
        
        }
    
        public static MyObject getInstance(){
        return MyObjectHandler.myObject;
        }
    
        protected  Object readResolve() throws ObjectStreamException{

        System.out.println("調用了readResolve方法!");
        return MyObjectHandler.myObject;
        }
    
    }

        使用時 MyObject mo = MyObject.getInstance()是單例的。

    序列化 一個對象其實就是,把一個對象通過存成文件,然後在從文件中讀出對象。

    2.靜態代碼塊中的代碼在實用類的時候就已經執行了,所以可以利用靜態代碼塊的這個特性來實現單例模式

    
    七 

    1.  線程對象在不同的運行時期有不同的狀態,狀態信息就存在於State枚舉類中,

    NEW:至今尚未啓動的線程處於這種狀態。

        RUNNABLE:正在Java虛擬機中執行的線程處於這種狀態。

    BLOCKED: 受阻塞並等待某個監視器鎖的線程處於這種狀態

    WAITING: 無限期地等待另一個線程來執行某一特定操作的線程處於這種狀態

    TIMED WAITING: 等待另一個線程來執行取決於指定等待時間的操作的線程處於這種狀態。

    TERMINATED: 已退出的線程處於這種狀態。

   2.  線程組:可以把線程歸屬到某一個線程組中,線程組中可以有線程對象,也可以有線程組,組中還可以有線程

       線程組的作用是,可以批量的管理線程或線程組對象,有效地對線程或線程組對象進行組織。

    
       線程對象關聯線程組:1級關聯就是父對象有子對象,但並不創建子孫對象。

       線程組自動歸到當前線程組中。在實例化一個ThreadGroup線程組x時如果不指定所屬的線程組,則x線程組自動歸到當前線程對象所屬的線程組中。

       JVM的根線程組是system,再取父線程組則出現空異常。
 
   3.  通過將線程歸屬到線程組中,當調用線程組的interrupt()方法時,可以將該組中的所有正在運行的線程批量停止。
    
   4.  遞歸與非遞歸取得組內對象

    ThreadGroup[] threadGroup = new ThreadGroup[Thread.currentThread().getThreadGroup().activeCount()];
        Thread.currentThread().getThreadGroup().enumerate(threadGroup,true/false); //傳true 遞歸,傳false 非遞歸

    所謂遞歸就是可以遍歷組中組,非遞歸只能遍歷本組下的組                                                                                                                   
   5. 使線程具有有序性,原理就是wait() 與notifyAll()結合使用,類似生產與消費者模式。
 
   SimpleDateFormat 非線程安全,使用單例的SimpleDateFormat類在多線程的環境中處理日期,極易出現日期轉換錯誤的情況。解決辦法使用多個

   SimpleDateFormat類的實例。ThreadLocal類能使線程綁定到指定對象,使用該類也可以解決多線程環境下SimpleDateFormat類處理錯誤的情況。

   6. UncaughtExceptionHandler類,可以對發生的異常進行有效的處理。線程對象的setUncaughtExceptionHandler()作用是對指定的線程對象設置默認的

     異常處理器。setDefaultUncaughtExceptionHandler()的作用是爲指定線程類的所有線程對象設置默認的異常處理器。
    

拓展:創建線程的第三種方式是,跟實現Runnable接口差不多,new Thread(new FutureTask<T>(new Callable<T>(){ 重寫call() }))

    實現Callable接口重寫Call()方法,創建一個對象傳給FutureTask的一個對象,讓後把該對象做參數傳給Thread();

    採用實現Runnable、Callable接口的方式創建多線程時,優勢是:線程類只是實現了Runnable接口或Callable接口,還可以繼承其他類。

    在這種方式下,多個線程可以共享同一個target對象,所以非常適合多個相同線程來處理同一份資源的情況,從而可以將CPU、代碼和數據分開,形成清晰的模

        型,較好地體現了面向對象的思想。
    
    劣勢是:

    編程稍微複雜,如果要訪問當前線程,則必須使用Thread.currentThread()方法。

    採用繼承Thread類方式:

    (1)優點:編寫簡單,如果需要訪問當前線程,無需使用Thread.currentThread()方法,直接使用this,即可獲得當前線程。

    (2)缺點:因爲線程類已經繼承了Thread類,所以不能再繼承其他的父類。

    採用實現Runnable接口方式:

    (1)優點:線程類只是實現了Runable接口,還可以繼承其他的類。在這種方式下,可以多個線程共享同一個目標對象,所以非常適合多個相同線程來處理同一

            份資源的情況,從而可以將CPU代碼和數據分開,形成清晰的模型,較好地體現了面向對象的思想。

    (2)缺點:編程稍微複雜,如果需要訪問當前線程,必須使用Thread.currentThread()方法。

    線程池創建線程 例: ExecutorService es= Executors.newCachedThreadPool();  es.execute(Runnable對象)

    https://blog.csdn.net/m0_37840000/article/details/79756932(線程池詳解)

     自定義線程池,可以用ThreadPoolExecutor類創建,它有多個構造方法來創建線程池,用該類很容易實現自定義的線程池,這裏先貼上示例程序:
    
] view plai

複製代碼
import java.util.concurrent.ArrayBlockingQueue;   
import java.util.concurrent.BlockingQueue;   
import java.util.concurrent.ThreadPoolExecutor;   
import java.util.concurrent.TimeUnit;   
  
public class ThreadPoolTest{   
    public static void main(String[] args){   
        //創建等待隊列   
        BlockingQueue<Runnable> bqueue = new ArrayBlockingQueue<Runnable>(20);   
        //創建線程池,池中保存的線程數爲3,允許的最大線程數爲5  
        ThreadPoolExecutor pool = new ThreadPoolExecutor(3,5,50,TimeUnit.MILLISECONDS,bqueue);   
        //創建七個任務   
        Runnable t1 = new MyThread();   
        Runnable t2 = new MyThread();   
        Runnable t3 = new MyThread();   
        Runnable t4 = new MyThread();   
        Runnable t5 = new MyThread();   
        Runnable t6 = new MyThread();   
        Runnable t7 = new MyThread();   
        //每個任務會在一個線程上執行  
        pool.execute(t1);   
        pool.execute(t2);   
        pool.execute(t3);   
        pool.execute(t4);   
        pool.execute(t5);   
        pool.execute(t6);   
        pool.execute(t7);   
        //關閉線程池   
        pool.shutdown();   
    }   
}   
  
class MyThread implements Runnable{   
    @Override   
    public void run(){   
        System.out.println(Thread.currentThread().getName() + "正在執行。。。");   
        try{   
            Thread.sleep(100);   
        }catch(InterruptedException e){   
            e.printStackTrace();   
        }   
    }   
}  

public ThreadPoolExecutor (int corePoolSize, int maximumPoolSize, long         keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue)
 

corePoolSize:線程池中所保存的線程數,包括空閒線程。

maximumPoolSize:池中允許的最大線程數。

keepAliveTime:當線程數大於核心數時,該參數爲所有的任務終止前,多餘的空閒線程等待新任務的最長時間。

unit:等待時間的單位。

workQueue:任務執行前保存任務的隊列,僅保存由execute方法提交的Runnable任務。
    
    
          


      

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