四 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();}}

推荐阅读