四 Java多線程-ThreadPool線程池-2( 二 )


/** * 有界阻塞隊列 */public class ArrayBlockingQueueTest {public static void main(String[] args) {ExecutorService service = new ThreadPoolExecutor(// 要處理的線程數超過maximumPoolSize+ workQueue.SIZE時,拋出異常1,2,1000,TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());// 因為 maximumPoolSize(2) + ArrayBlockingQueue.SIZE(10) < 13 , 所以會拋出異常for (int i = 0; i < 13; i++) {service.execute(() ->System.out.println("當前線程 " + Thread.currentThread().getName()));}service.shutdown();}}再來看看ArrayBlockingQueue的另一個例子 , 可以加深印象:
public class ArrayBlockingQueueTester {public static BlockingQueue<String> queue = new ArrayBlockingQueue<String>(5);// 一個往里放class Producer implements Runnable {@Overridepublic void run() {try {queue.put("川菜");System.out.println(Thread.currentThread().getName() + " 廚師做好 川菜");} catch (InterruptedException e) {e.printStackTrace();}}}// 一個往外拿class Consumer implements Runnable {@Overridepublic void run() {try {String food = queue.take();System.out.println(Thread.currentThread().getName() + " 客人消費 " + food);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {// 客人等著菜for (int i = 0; i < 5; i++) {new Thread(new ArrayBlockingQueueTester().new Consumer()).start();}// 廚師做好菜for (int i = 0; i < 5; i++) {new Thread(new ArrayBlockingQueueTester().new Producer()).start();}}}ArrayBlockingQueue說白了就是一個往里放,一個往外拿:

1、往里放的 , 只能最多放指定個數就不能再放了(阻塞,等待,這里是5個);
2、往外拿的,如果沒有可以拿的了 , 就等著(阻塞,等待) 。
咱們點菜的時候不就是這樣嗎?
LinkedBlockingQueue這個就牛逼了,相當于無底洞,有多少處理多少,此時線程池能夠創建的最大線程數是corePoolSize,而maximumPoolSize就成了擺設,這等于說是完全取決于系統的性能 。
/** * 無界阻塞隊列 */public class LinkedBlockingQueueTest {public static void main(String[] args) {// 要處理的線程數過大時,是否拋出異常,取決于機器的性能ExecutorService service = new ThreadPoolExecutor(1,2,1000,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>(),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());for (int i = 0; i < 10000; i++) {service.execute(() ->System.out.println("當前線程 " + Thread.currentThread().getName()));}service.shutdown();}}最后一個隊列是PriorityBlockingQueue,它是一種有優先級的無界阻塞隊列 , 默認的元素執行順序是升序,可以通過自定義接口Comparable<T>實現compareTo()方法來指定隊列中的元素執行順序 。
【四 Java多線程-ThreadPool線程池-2】/** * 測試類 */public class Test1 implements Runnable, Comparable<Test1> {private int priority;public Test1(int priority) {this.priority = priority;}public int getPriority() {return priority;}public void setPriority(int priority) {this.priority = priority;}@Overridepublic int compareTo(Test1 o) {// 返回1時為升序// 返回-1為降序return this.priority > o.priority ? -1 : 1;}@Overridepublic void run() {System.out.println("當前線程 " +Thread.currentThread().getName() +", priority = " +this.priority);}}/** * 有優先級的無界阻塞隊列 */public class PriorityBlockingQueueTest {public static void main(String[] args) {ExecutorService service = new ThreadPoolExecutor(1,2,1000,TimeUnit.MILLISECONDS,new PriorityBlockingQueue<>(),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());for (int i = 0; i < 10; i++) {service.execute(new Test1(i));}service.shutdown();}}如果想在線程池的執行線程中加入一點自己希望的動作,可以通過自定義ThreadFactory實現 。
/** * 測試類 */public class Test2 implements Runnable {private String name;public Test2(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic void run() {System.out.println(this.getName() + ",當前線程 " + Thread.currentThread().getName());}}/** * 自定義ThreadFactory */public class SelfDefineThreadPoolExecutor {public static void main(String[] args) {ExecutorService service = new ThreadPoolExecutor(1,2,1000,TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(8),// 自定義ThreadFactorynew ThreadFactory() {@Overridepublic Thread newThread(Runnable r) {System.out.println("線程 " + r.hashCode() + " 創建");return new Thread(r, "thread-pool-" + r.hashCode());}},// 加入自定義動作new ThreadPoolExecutor.CallerRunsPolicy()) {public void beforeExecute(Thread thread, Runnable runnable) {System.out.println(((Test2) runnable).getName() + " 準備執行");}public void afterExecute(Thread thread, Runnable runnable) {System.out.println(((Test2) runnable).getName() + " 執行完畢");}public void terminated() {System.out.println("線程池關閉");}};for (int i = 0; i < 10; i++) {service.execute(new Test2("Test2" + i));}service.shutdown();}}

推薦閱讀