为什么要用线程池?
每次用线程的时候都去new一个,不麻烦么。如果线程用到较少可以。当需要大量用到线程时,频繁的创建线程,而且创建线程和销毁带来的开销也会随之增多。
线程池就像一个执行器。而我们需要执行的业务逻辑,在我们编写的实现了Runnable接口的run方法里面。
需要执行就扔到线程池里,我只要保证我的业务逻辑在run里面已经实现了。执行找线程池这个代工。
线程池ThreadPoolExecutor类,下面是该类的构造方法。
public class ThreadPoolExecutor extends AbstractExecutorService { ..... public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> 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<Runnable>:缓存队列中允许最大的任务线程数(当线程数大于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<Runnable>(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 已执行完的线程数:0
task:1执行
线程池中的线程数:3 队列中等待的线程数:0 已执行完的线程数:0
task:2执行
线程池中的线程数:4 队列中等待的线程数:0 已执行完的线程数:0
task:3执行
线程池中的线程数:5 队列中等待的线程数:0 已执行完的线程数:0
task:4执行
线程池中的线程数:5 队列中等待的线程数:1 已执行完的线程数:0
线程池中的线程数:5 队列中等待的线程数:2 已执行完的线程数:0
线程池中的线程数:5 队列中等待的线程数:3 已执行完的线程数:0
线程池中的线程数:5 队列中等待的线程数:4 已执行完的线程数:0
线程池中的线程数:5 队列中等待的线程数:5 已执行完的线程数:0
线程池中的线程数:6 队列中等待的线程数:5 已执行完的线程数:0
task:10执行
线程池中的线程数:7 队列中等待的线程数:5 已执行完的线程数:0
task:11执行
task:12执行
线程池中的线程数:8 队列中等待的线程数:5 已执行完的线程数:0
线程池中的线程数:9 队列中等待的线程数:5 已执行完的线程数:0
task:13执行
task:14执行
线程池中的线程数:10 队列中等待的线程数:5 已执行完的线程数:0
task: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