Java线程池ThreadPoolExecutor

1、函数介绍

new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue)

ThreadPoolExecutor:
corePoolSize:       核心线程数,线程池维护线程的最少数量,即建议线程数
maximumPoolSize:线程池维护线程的最大数量(线程池里最大有corePoolSize个线程可运行)
keepAliveTime:     线程池维护线程所允许的空闲时间(当一个线程不工作时候,过keepAliveTime长时间将停止该线程)
unit:                      线程池维护线程所允许的空闲时间的单位(keepAliveTime的单位)
workQueue:           线程池所使用的缓冲队列(存放需要被线程池执行的线程队列)
handler:                 线程池对拒绝任务的处理策略(添加任务失败后处理方式:
    1、AbortPolicy:              直接抛出一个RejectedExecutionException异常
    2、DiscardPolicy:           什么也不做,任务自然被直接丢掉
    3、DiscardOldestPolicy:如果线程池没有被shutdown,则会从BlockingQueue里取出一个任务,然后执行execute方法
    4、CallerRunsPolicy:       如果线程池没有被shutdown,则会直接调用任务的run()方法,不过没有开启一个新的线程或交个线程池调度,而是直接使用生产者的当前线程来运行)

2、运行机制

线程池运行机制:

    1、当调用execute()方法添加一个任务时候,线程池做以下判断:

        a、如果正在运行的线程数 < corePoolSize,那就马上创建线程并运行这个任务,而不会进行排队。

        b、如果正在运行的线程数 >= corePoolSize,那就把这个任务放入队列。

        c、如果队列满了,并且正在运行的线程数 < maximumPoolSize,那么还是要创建线程并运行这个任务。

        d、如果队列满了,并且正在运行的线程数 >= maximumPoolSize,那么线程池就会调用handler里方法。(采用LinkedBlockingDeque就不会出现队列满情况)

    2、当一个线程完成任务时,它会从队列里取下一个任务来执行。

    3、当一个线程执行完后,超过keepAliveTime时,线程池会判断,如果当前运行线程数 > corePoolSize,就会把这个线程停掉,到最后保持corePoolSize的大小。

3、Demo

情况1:  

采用 LinkedBlockingDeque<Runnable>队列 队列大小没有限制不会出现 机制1中d的情况。

public class demo {
	private static int corepoolsize = 2;
	private static int maxpoolsize = 5;
	private static int keepalivetime = 1;	
	public static void main(String[] args) {
		LinkedBlockingDeque<Runnable> queue = new LinkedBlockingDeque<Runnable>();
		
		ThreadPoolExecutor threadpool = new ThreadPoolExecutor(
					corepoolsize,
					maxpoolsize,
					keepalivetime,
					TimeUnit.SECONDS,
					queue,
					new ThreadPoolExecutor.AbortPolicy()
				);
		
		for(int i=0;i<10;i++){
			threadpool.execute(new ThreadPoolTask(String.valueOf(i)));
			System.out.println("当前队列大小  "+queue.size());
		}
		threadpool.shutdown();
	}
}

class ThreadPoolTask implements Runnable{	
	private String thName = null;
	
	public ThreadPoolTask(String name) {
		this.thName = name;
	}
	
	public void run() {
		System.out.println("I am "+this.thName+" start");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("I am "+this.thName+" end");
	}
}

输出结果:

I am 0 start
当前队列大小  0
当前队列大小  0
I am 1 start
当前队列大小  1
当前队列大小  2
当前队列大小  3
当前队列大小  4
当前队列大小  5
当前队列大小  6
当前队列大小  7
当前队列大小  8
I am 0 end
I am 2 start
I am 1 end
I am 3 start
I am 3 end
I am 2 end
I am 4 start
I am 5 start
I am 5 end
I am 4 end
I am 6 start
I am 7 start
I am 7 end
I am 8 start
I am 6 end
I am 9 start
I am 8 end
I am 9 end

情况2:

采用 ArrayBlockingQueue<Runnable>(3)    设置队列大小为3 corepoolsize = 2 maxpoolsize = 5

此时线程池的总容量 = 队列大小 + maxpoolsize,为8

当创建10个线程时,但只能同时让8个线程运行,插入第九个时就会调用handler方法,这里设置的是AbortPolicy


注意:

这里每个线程里我都sleep(1000),保证了在创建第九个线程的时候,前8个线程都在运行状态,线程池是满的,所以创建时会抛出异常。

如果取消每个线程里sleep,之前线程执行完后就会被线程池回收空间,线程池处于不满的状态,就可以继续创建线程。

public class demo {
	private static int corepoolsize = 2;
	private static int maxpoolsize = 5;
	private static int keepalivetime = 1;
	private static int queuesize = 3;
	public static void main(String[] args) {
		ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(queuesize);
		
		ThreadPoolExecutor threadpool = new ThreadPoolExecutor(
					corepoolsize,
					maxpoolsize,
					keepalivetime,
					TimeUnit.SECONDS,
					queue,
					new ThreadPoolExecutor.AbortPolicy()
				);
		
		for(int i=1;i<=10;i++){
			threadpool.execute(new ThreadPoolTask(String.valueOf(i)));
			System.out.println("当前队列大小  "+queue.size());
		}
		threadpool.shutdown();
	}
}

class ThreadPoolTask implements Runnable{
	
	private String thName = null;
	
	public ThreadPoolTask(String name) {
		this.thName = name;
	}
	
	public void run() {
		System.out.println("I am "+this.thName+" start");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("I am "+this.thName+" end");
	}
}

输出结果:

当前队列大小  0
当前队列大小  0
当前队列大小  1
当前队列大小  2
I am 2 start
当前队列大小  3
I am 1 start
I am 6 start
当前队列大小  3
当前队列大小  3
I am 7 start
当前队列大小  3
I am 8 start
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.fedomn.demo.ThreadPoolTask@6a3522b5 rejected from java.util.concurrent.ThreadPoolExecutor@67291479[Running, pool size = 5, active threads = 5, queued tasks = 3, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372)
	at com.fedomn.demo.demo.main(demo.java:25)
I am 2 end
I am 3 start
I am 7 end
I am 4 start
I am 6 end
I am 5 start
I am 1 end
I am 8 end
I am 3 end
I am 5 end
I am 4 end		

4、总结

总结:

1、线程池 可以 处在运行状态的线程数 = maximumPoolSize

2、线程池可以承受的最大线程数(容量) = maximumPoolSize + 线程队列大小

3、当线程池满时 添加线程会有三种方式add抛异常 offer返回Boolean值 put直到添加成功为止 正好对应handle的处理方法 可以自己到API寻找


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值