线程池ThreadPool简单使用
ThreadPoolExecutor可以用来创建线程池,例如:
1 ThreadPoolExecutor executor=new ThreadPoolExecutor(10,13, 2 200,TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(5));
ThreadPoolExecutor 构造函数为:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
其中各参数的含义:
corePoolSize:
线程池启动后,在池中保持的线程的最小数量。需要说明的是线程数量是逐步到达corePoolSize值的。例如corePoolSize被设置为10,而任务数量只有5,则线程池中最多会启动5个线程,而不是一次性地启动10个线程。
maxinumPoolSize:
线程池中能容纳的最大线程数量,如果超出,则使用RejectedExecutionHandler拒绝策略处理。
keepAliveTime:
线程的最大生命周期。这里的生命周期有两个约束条件:一:该参数针对的是超过corePoolSize数量的线程;二:处于非运行状态的线程。举个例子:如果corePoolSize(最小线程数)为10,maxinumPoolSize(最大线程数)为20,而此时线程池中有15个线程在运行,过了一段时间后,其中有3个线程处于等待状态的时间超过keepAliveTime指定的时间,则结束这3个线程,此时线程池中则还有12个线程正在运行。
unit:
这是keepAliveTime的时间单位,可以是纳秒,毫秒,秒,分钟等。
workQueue:
任务队列。当线程池中的线程都处于运行状态,而此时任务数量继续增加,则需要一个容器来容纳这些任务,这就是任务队列。这个任务队列是一个阻塞式的单端队列。
threadFactory:
定义如何启动一个线程,可以设置线程的名称,并且可以确定是否是后台线程等。
handler:
拒绝任务处理器。由于超出线程数量和队列容量而对继续增加的任务进行处理的程序。
具体实例:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadPool {
public static void main(String[] args) {
//如果Executors提供的三个静态方法能满足要求,就尽量使用它提供的三个方法,因为自己去手动配置ThreadPoolExecutor的参数有点麻烦,要根据实际任务的类型和数量来进行配置
ThreadPoolExecutor executor=new ThreadPoolExecutor(10,13,
200,TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(5));
for(int i=0;i<18;i++)
{
MyTask myTask=new MyTask(i);
executor.execute(myTask);//提交线程
System.out.println("线程池中的线程数目:"+executor.getPoolSize()+
"队列中等待执行的任务数目:"+executor.getQueue().size()+
"已经执行完的任务数目:"+executor.getCompletedTaskCount());
}
executor.shutdown();//启动有序关闭,
}
}
class MyTask implements Runnable {
private int taskName;
public MyTask(int num){
this.taskName=num;
}
public void run(){
System.out.println("正在执行:"+taskName);
try
{
Thread.currentThread().sleep(4000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println("task"+taskName+"执行完毕");
}
}
不过在java doc中,并不提倡我们直接使用ThreadPoolExecutor,而是使用Executors类中提供的几个静态方法来创建线程池:
Executors.newCachedThreadPool();
//创建一个缓冲池,缓冲池容量大小为Integer.MAX_VALUE
Executors.newSingleThreadExecutor();
//创建容量为1的缓冲池
Executors.newFixedThreadPool(
int
);
//创建固定容量大小的缓冲池
从它们的具体实现来看,它们实际上也是调用了ThreadPoolExecutor,只不过参数都已配置好了。
newFixedThreadPool创建的线程池corePoolSize和maximumPoolSize值是相等的,它使用的LinkedBlockingQueue;
newSingleThreadExecutor将corePoolSize和maximumPoolSize都设置为1,也使用的LinkedBlockingQueue;
newCachedThreadPool将corePoolSize设置为0,将maximumPoolSize设置为Integer.MAX_VALUE,使用的SynchronousQueue,也就是说来了任务就创建线程运行,当线程空闲超过60秒,就销毁线程。
实际中,如果Executors提供的三个静态方法能满足要求,就尽量使用它提供的三个方法,因为自己去手动配置ThreadPoolExecutor的参数有点麻烦,要根据实际任务的类型和数量来进行配置。
参考:https://www.cnblogs.com/dolphin0520/p/3932921.html
posted on 2018-10-30 16:36 最后一个java菜鸟 阅读(2216) 评论(0) 编辑 收藏 举报