为什么要用线程池?
每次用线程的时候都去new一个,不麻烦么。如果线程用到较少可以。当需要大量用到线程时,频繁的创建线程,而且创建线程和销毁带来的开销也会随之增多。
线程池就像一个执行器。而我们需要执行的业务逻辑,在我们编写的实现了Runnable接口的run方法里面。
需要执行就扔到线程池里,我只要保证我的业务逻辑在run里面已经实现了。执行找线程池这个代工。
线程池ThreadPoolExecutor类,下面是该类的构造方法。
public class ThreadPoolExecutor extends AbstractExecutorService { ..... public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueueworkQueue); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue workQueue,ThreadFactory threadFactory); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue workQueue,RejectedExecutionHandler handler); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler); ...}
主要参数介绍:
corePoolSize:核心线程数
maximumPoolSize:最大线程数(可以想象成cpu中的超超频)
keepAliveTime:线程无任务存活时间(一般情况下,当前线程数poolSize大于corePoolSize时,会销毁空闲时间大于keepAliveTime的线程,直到当前线程数不大于corePoolSize)
unit:keepAliveTime的单位(
TimeUnit.DAYS; //天TimeUnit.HOURS; //小时TimeUnit.MINUTES; //分钟TimeUnit.SECONDS; //秒TimeUnit.MILLISECONDS; //毫秒TimeUnit.MICROSECONDS; //微妙TimeUnit.NANOSECONDS; //纳秒
) BlockingQueue:缓存队列中允许最大的任务线程数(当线程数大于maxnumPoolSize时,将加入到缓存队列中)
ThreaPoolExecutor的一些方法: execute():线程池加入线程 submit():线程池加入线程(和execute方法一样,只不过会返回一个参数。ps:其实submit内部也是调用了execute方法) shutdown():关闭线程池(若线程池和缓存中还有未执行完的线程,则会继续执行,执行完清空线程池。) shutdownNow():马上关闭线程池(若线程池中还有未执行完的线程,则会抛出异常) 简单的例子:
package code.thread;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;//线程池public class ThreadPool { public static void main(String[] args) { ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MICROSECONDS, new ArrayBlockingQueue(5)); for(int i=0;i<15;i++){ threadPool.execute(new Task(i)); System.out.println("线程池中的线程数:"+threadPool.getPoolSize()+" 队列中等待的线程数:"+ threadPool.getQueue().size()+" 已执行完的线程数:"+threadPool.getCompletedTaskCount()); } { try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("线程池中的线程数:"+threadPool.getPoolSize()+" 队列中等待的线程数:"+ threadPool.getQueue().size()+" 已执行完的线程数:"+threadPool.getCompletedTaskCount()); } threadPool.shutdown(); }}class Task implements Runnable { private int i; public Task(int i) { this.i = i; } @Override public void run() { System.out.println("task:"+i+"执行"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("task:"+i+"执行结束"); } }
执行结果:
task:0执行
线程池中的线程数:1 队列中等待的线程数:0 已执行完的线程数:0线程池中的线程数:2 队列中等待的线程数:0 已执行完的线程数:0task:1执行线程池中的线程数:3 队列中等待的线程数:0 已执行完的线程数:0task:2执行线程池中的线程数:4 队列中等待的线程数:0 已执行完的线程数:0task:3执行线程池中的线程数:5 队列中等待的线程数:0 已执行完的线程数:0task:4执行线程池中的线程数:5 队列中等待的线程数:1 已执行完的线程数:0线程池中的线程数:5 队列中等待的线程数:2 已执行完的线程数:0线程池中的线程数:5 队列中等待的线程数:3 已执行完的线程数:0线程池中的线程数:5 队列中等待的线程数:4 已执行完的线程数:0线程池中的线程数:5 队列中等待的线程数:5 已执行完的线程数:0线程池中的线程数:6 队列中等待的线程数:5 已执行完的线程数:0task:10执行线程池中的线程数:7 队列中等待的线程数:5 已执行完的线程数:0task:11执行task:12执行线程池中的线程数:8 队列中等待的线程数:5 已执行完的线程数:0线程池中的线程数:9 队列中等待的线程数:5 已执行完的线程数:0task:13执行task:14执行线程池中的线程数:10 队列中等待的线程数:5 已执行完的线程数:0task:0执行结束task:2执行结束task:5执行task:1执行结束task:6执行task:3执行结束task:8执行task:4执行结束task:9执行task:13执行结束task:7执行task:10执行结束task:11执行结束task:12执行结束task:14执行结束task:5执行结束task:6执行结束task:7执行结束task:9执行结束task:8执行结束线程池中的线程数:5 队列中等待的线程数:0 已执行完的线程数:15