天天看點

java多線程(三)

線程狀态轉化圖

[img]http://dl2.iteye.com/upload/attachment/0125/8008/d4811fc5-e155-3be6-b55a-2b7e3c4e568f.jpg[/img]

這個圖我覺得應該是市面比較通俗易懂的多線程狀态轉換圖,wait()和sleep()的差別顯而易見,wait會釋放鎖然後等待notify()、notifyAll()才會激活然後等待獲得該對象鎖之後進入可運作狀态,而sleep()則是在指定的時間内一直阻塞着線程,到時間後才會進入可運作狀态。大家可以自己寫個小程式按照圖上面的過程實踐嘗試一把Thread 有個getState()可以檢視目前線程的狀态!

[img]http://dl2.iteye.com/upload/attachment/0125/8018/fe1b1844-0a96-3ecf-9789-daecb900c0b4.png[/img]

[img]http://dl2.iteye.com/upload/attachment/0125/8828/637f6a2c-270a-3b23-994f-50dd0bd9c553.png[/img]

[img]http://dl2.iteye.com/upload/attachment/0125/8022/beb8a63b-c685-373c-bab0-56cd9835a3ba.png[/img]

線程進入BLOCKED狀态(很顯然A執行後B一直在阻塞中,等待A執行完成後,B才執行完成)

[img]http://dl2.iteye.com/upload/attachment/0125/8820/a95c4743-4cae-30d9-8a32-1656449eb5d4.png[/img]

[img]http://dl2.iteye.com/upload/attachment/0125/8826/ce3bc591-ded4-341e-b0a8-9cd458808192.png[/img]

[img]http://dl2.iteye.com/upload/attachment/0125/8824/41220eb1-3bcd-3686-8076-645b88fe66c6.png[/img]

線程池:

Java通過Executors工廠類來産生連接配接池,該工廠類中包含如下的幾個靜态工程方法來建立連接配接池:

1、public static ExecutorService newFixedThreadPool(int nThreads):建立一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。

2、public static ExecutorService newSingleThreadExecutor():建立一個單線程化的線程池,它隻會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。

3、public static ExecutorService newCachedThreadPool():建立一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則建立線程。

4、public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize):建立具有指定線程數的線程池,它可以再指定延遲後執行線程任務,corePoolSize指池中所儲存的線程數,即使線程是空閑的也被儲存線上程池内。

二、ExecutorService類

可以看到上面的5個方法中,前面3個方法的傳回值都是一個ExecutorService對象。該ExecutorService對象就代表着一個盡快執行線程的線程池(隻要線程池中有空閑線程立即執行線程任務),程式隻要将一個Runnable對象或Callable對象送出給該線程池即可,該線程就會盡快的執行該任務。

ExecutorService有幾個重要的方法:

1、isShutdown() 如果此執行程式已關閉,則傳回 true。

2、isTerminated() 如果關閉後所有任務都已完成,則傳回 true。

3、shutdown() 啟動一次順序關閉,執行以前送出的任務,但不接受新任務。

4、 List<Runnable> shutdownNow()

試圖停止所有正在執行的活動任務,暫停處理正在等待的任務,并傳回等待執行的任務清單。

5、<T> Future<T> submit(Callable<T> task)

送出一個傳回值的任務用于執行,傳回一個表示任務的未決結果的 Future。

6、Future<?> submit(Runnable task)

送出一個 Runnable 任務用于執行,并傳回一個表示該任務的 Future。

7、<T> Future<T> submit(Runnable task, T result)

送出一個 Runnable 任務用于執行,并傳回一個表示該任務的 Future。

更詳細的參考JDK API文檔。

submit方法是對 Executor接口execute方法的更好的封裝,建議使用submit方法。

1.newFixedThreadPool的使用

[img]http://dl2.iteye.com/upload/attachment/0125/9659/7b673b87-0c39-3fc4-ac1c-4679440de39b.png[/img]

[img]http://dl2.iteye.com/upload/attachment/0125/9661/9e32fb01-a800-3503-9e8b-f6b6f10a6a40.png[/img]

[img]http://dl2.iteye.com/upload/attachment/0125/9663/1cc2c724-1c03-3ef0-a85b-8b9bb17aa301.png[/img]

因為我建立的是一個大小為2的固定長度線程池,根據輸出可以看出隻有一開始是一起建立了兩個線程因為此時線程已經滿了這時已經不在建立線程了而是開始執行了後面是執行完一個線程就在建立一個線程,直到把要建立的5都建立并執行完畢。

2.newSingleThreadExecutor的使用

[img]http://dl2.iteye.com/upload/attachment/0125/9665/c5dc3479-90e4-3257-9ac5-75a67f4f05c0.png[/img]

[img]http://dl2.iteye.com/upload/attachment/0125/9667/960d99c9-0dc3-33c1-8137-b85b3691cbd9.png[/img]

根據輸出可有看到從始至終隻有一個線程在執行

3.newCachedThreadPool的使用

[img]http://dl2.iteye.com/upload/attachment/0125/9669/f6485852-9261-3bdb-a29c-1155ad913036.png[/img]

[img]http://dl2.iteye.com/upload/attachment/0125/9671/cee7276d-0e32-3b01-b781-82b227a556d7.png[/img]

可變線程池會動态的根據生成的線程數直接複用或建立線程

4.newScheduledThreadPool 延時線程池

[img]http://dl2.iteye.com/upload/attachment/0125/9673/28e5da35-17bc-367b-830d-d4975f1bfa3f.png[/img]

[img]http://dl2.iteye.com/upload/attachment/0125/9675/7570d627-98a5-3e54-a0c0-99a435cf5045.png[/img]