手写线程池(六)

题外话:

在面试的时候,如果面试官问你:你在工作中单一的/固定数的/可变你的三种创建线程池的方法,你用哪个多?

答:一个都不用,我们都是自己手写的。因为阿里巴巴开发手册里面明确的提到: 线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式。

一:手写一个线程池采用AbortPolicy拒绝策略的代码如下:

package com.mszl.thread;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 功能:手写一个线程池
 * 备注:更多资料请访问 http://www.91mszl.com
 * @author bobo teacher
 */
public class ThreadPoolDiyDemo {
	
	public static void main(String[] args) {
		// int corePoolSize:2
		// int maximumPoolSize:5
		// long keepAliveTime, 1
		// TimeUnit unit,
		// BlockingQueue workQueue:3
		// ThreadFactory threadFactory,
		// RejectedExecutionHandler handler
		ExecutorService threadPool=new ThreadPoolExecutor(2, 5, 
				1, TimeUnit.SECONDS, 
				new LinkedBlockingQueue(3), 
				Executors.defaultThreadFactory(), 
				new ThreadPoolExecutor.AbortPolicy());
		
		// 模拟10个用户到银行的5个窗口去取钱
		try{
			for(int i=1; i<=7; i++){
				threadPool.execute(new Runnable() {
					public void run() {
						System.out.println(Thread.currentThread().getName() + "\t" + "办理完成");
					}
				});
			}
		} catch(Exception ex){
			ex.printStackTrace();
		} finally{
			threadPool.shutdown(); // 关闭线程池
		}
	}
	

}

当模拟7个用户取钱时执行结果为:

pool-1-thread-1	办理完成
pool-1-thread-1	办理完成
pool-1-thread-1	办理完成
pool-1-thread-1	办理完成
pool-1-thread-2	办理完成
pool-1-thread-3	办理完成
pool-1-thread-4	办理完成

当模拟9个用户取钱时执行结果为:

pool-1-thread-1	办理完成
pool-1-thread-3	办理完成
pool-1-thread-2	办理完成
pool-1-thread-1	办理完成
pool-1-thread-5	办理完成
pool-1-thread-3	办理完成
pool-1-thread-4	办理完成
pool-1-thread-1	办理完成
java.util.concurrent.RejectedExecutionException: Task com.mszl.thread.ThreadPoolDiyDemo$1@1f96302 rejected from java.util.concurrent.ThreadPoolExecutor@14eac69[Running, pool size = 5, active threads = 0, queued tasks = 0, completed tasks = 8]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
	at com.mszl.thread.ThreadPoolDiyDemo.main(ThreadPoolDiyDemo.java:37)

分析:因为我们模拟的是9个用户大于了8个(最大线程数5+队列数3=8),并且我们采用的是默认的AbortPolicy拒绝策略,根据AbortPolicy的特性,直接抛异常。

 

二:手写一个线程池采用 CallerRunPolicy拒绝策略的代码如下:

package com.mszl.thread;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 功能:手写一个线程池
 * 备注:更多资料请访问 http://www.91mszl.com
 * @author bobo teacher
 */
public class ThreadPoolDiyDemo {
	
	public static void main(String[] args) {
		// int corePoolSize:2
		// int maximumPoolSize:5
		// long keepAliveTime, 1
		// TimeUnit unit,
		// BlockingQueue workQueue:3
		// ThreadFactory threadFactory,
		// RejectedExecutionHandler handler
		ExecutorService threadPool=new ThreadPoolExecutor(2, 5, 
				1, TimeUnit.SECONDS, 
				new LinkedBlockingQueue(3), 
				Executors.defaultThreadFactory(), 
				new ThreadPoolExecutor.CallerRunsPolicy());
		
		// 模拟10个用户到银行的5个窗口去取钱
		try{
			for(int i=1; i<=9; i++){
				threadPool.execute(new Runnable() {
					public void run() {
						System.out.println(Thread.currentThread().getName() + "\t" + "办理完成");
					}
				});
			}
		} catch(Exception ex){
			ex.printStackTrace();
		} finally{
			threadPool.shutdown(); // 关闭线程池
		}
	}
	

}

执行结果:

pool-1-thread-2	办理完成
pool-1-thread-4	办理完成
pool-1-thread-2	办理完成
pool-1-thread-3	办理完成
pool-1-thread-1	办理完成
pool-1-thread-5	办理完成
pool-1-thread-2	办理完成
pool-1-thread-4	办理完成
main	办理完成

分析:我们模拟的是9个用户大于了8个(最大线程数5+队列数3=8),并且我们采用的是CallerRunPolicy 拒绝策略,根据CallerRunPolicy 的特性,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量。所以有一个线程退回到了main线程。

 

三:手写一个线程池采用 DiscardOldestPolicy 拒绝策略的代码如下:

package com.mszl.thread;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 功能:手写一个线程池
 * 备注:更多资料请访问 http://www.91mszl.com
 * @author bobo teacher
 */
public class ThreadPoolDiyDemo {
	
	public static void main(String[] args) {
		// int corePoolSize:2
		// int maximumPoolSize:5
		// long keepAliveTime, 1
		// TimeUnit unit,
		// BlockingQueue workQueue:3
		// ThreadFactory threadFactory,
		// RejectedExecutionHandler handler
		ExecutorService threadPool=new ThreadPoolExecutor(2, 5, 
				1, TimeUnit.SECONDS, 
				new LinkedBlockingQueue(3), 
				Executors.defaultThreadFactory(), 
				new ThreadPoolExecutor.DiscardOldestPolicy());
		
		// 模拟10个用户到银行的5个窗口去取钱
		try{
			for(int i=1; i<=9; i++){
				threadPool.execute(new Runnable() {
					public void run() {
						System.out.println(Thread.currentThread().getName() + "\t" + "办理完成");
					}
				});
			}
		} catch(Exception ex){
			ex.printStackTrace();
		} finally{
			threadPool.shutdown(); // 关闭线程池
		}
	}
	

}

执行结果:

 

pool-1-thread-2 办理完成
pool-1-thread-1 办理完成
pool-1-thread-2 办理完成
pool-1-thread-3 办理完成
pool-1-thread-4 办理完成
pool-1-thread-2 办理完成
pool-1-thread-1 办理完成
pool-1-thread-5 办理完成

分析:我们模拟的是9个用户大于了8个(最大线程数5+队列数3=8),并且我们采用的是 DiscardOldestPolicy 拒绝策略,根据 DiscardOldestPolicy 的特性,抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。所以只有8个办理完成,还有一个被抛弃了。

 

四:手写一个线程池采用 DiscardPolicy 拒绝策略的代码如下:

package com.mszl.thread;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 功能:手写一个线程池
 * 备注:更多资料请访问 http://www.91mszl.com
 * @author bobo teacher
 */
public class ThreadPoolDiyDemo {
	
	public static void main(String[] args) {
		// int corePoolSize:2
		// int maximumPoolSize:5
		// long keepAliveTime, 1
		// TimeUnit unit,
		// BlockingQueue workQueue:3
		// ThreadFactory threadFactory,
		// RejectedExecutionHandler handler
		ExecutorService threadPool=new ThreadPoolExecutor(2, 5, 
				1, TimeUnit.SECONDS, 
				new LinkedBlockingQueue(3), 
				Executors.defaultThreadFactory(), 
				new ThreadPoolExecutor.DiscardPolicy());
		
		// 模拟10个用户到银行的5个窗口去取钱
		try{
			for(int i=1; i<=9; i++){
				threadPool.execute(new Runnable() {
					public void run() {
						System.out.println(Thread.currentThread().getName() + "\t" + "办理完成");
					}
				});
			}
		} catch(Exception ex){
			ex.printStackTrace();
		} finally{
			threadPool.shutdown(); // 关闭线程池
		}
	}
	

}

执行结果:

pool-1-thread-2	办理完成
pool-1-thread-2	办理完成
pool-1-thread-5	办理完成
pool-1-thread-4	办理完成
pool-1-thread-3	办理完成
pool-1-thread-1	办理完成
pool-1-thread-5	办理完成
pool-1-thread-2	办理完成

分析:我们模拟的是9个用户大于了8个(最大线程数5+队列数3=8),并且我们采用的是  DiscardPolicy 拒绝策略,根据  DiscardPolicy 的特性,直接丢弃任务,不予任何处理也不抛出异常。

你可能感兴趣的:(手写线程池(六))