您的位置:首页 > 其它

线程池相关内容整理

2018-02-02 20:28 411 查看


线程池

在整理线程池相关内容时,笔者阅读了 http://blog.csdn.net/gol_phing/article/details/49032055#t1 这位朋友的帖子
可以说总结的很详细,对源码的分析很透彻,笔者学习后进行了简单的总结来巩固一下自己的知识~

为了解决频繁的创建线程带来的内存的开销。可以通过线程池,不断的利用线程池中线程反复地执行给定的任务,来解决开销问题。


关于ThreadPoolExecutor

为了更好地控制多线程,JDK提供了一套Executor框架,帮助开发人员有效的进行线程控制,其本质就是一个线程池。其中ThreadPoolExecutor是线程池在中最核心的一个类,Executors的四个方法生成的四种线程池都是基于ThreadPoolExecutor实现的。 ThreadPoolExecutor提供了四个构造方法,下面是参数最多的(其他的都是重载):
public class ThreadPoolExecutor extends AbstractExecutorService {
public ThreadPoolExecutor(
int corePoolSize, //核心池的大小(即线程池中的线程数目大于这个参数时,提交的任务会被放进任务缓存队列)
int maximumPoolSize,  //线程池维护线程的最大数量
long keepAliveTime,    //线程池维护线程所允许空闲时间
TimeUnit unit, //线程池维护线程所允许空闲时间单位
BlockingQueue<Runnable> workQueue,    //线程池所使用的缓冲队列
ThreadFactory threadFactory,  //创建线程的工厂
RejectedExecutionHandler handler //线程池对拒绝任务的处理策略
);
}


线程池的执行过程

线程池刚创建时,里面没有线程。任务队列是作为参数传递进来的。就算队列里面有任务,线程池也不会马上执行它们;
当调用execute()方法添加一个任务时,线程池会做如下判断:
a. 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
​ b. 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列。
​ c. 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建线程运行这个任务;
​ d. 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常,告诉调用者“我不能再接受任务了”。
当一个线程完成任务时,它会从队列中取下一个任务来执行。
当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。


通过线程池创建多线程代码示例


1.使用ThreadPoolExecutor类

//首先提供一个实现Runnable的类描述具体线程任务
class MyTask implements Runnable {
private int taskNum;
public MyTask(int num) {
this.taskNum = num;
}

@Override
public void run() {
System.out.println("正在执行task "+taskNum);
try {
Thread.currentThread().sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task "+taskNum+"执行完毕");
}
}
//创建线程池提交任务
public class ExecuteTask{
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(5,10,200,TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(5));
for(int i=0;i<15;i++){
MyTask myTaks = new MyTask(i);
executor.execute(myTask);
System.out.println("线程池中线程数目:"+executor.getPoolSize()+",队列中等待执行的任务数目:"+
executor.getQueue().size()+",已执行玩别的任务数目:"+executor.getCompletedTaskCount());
}
executor.shutdown();//关闭线程
}
}


2.通过Executors类得到线程池对象



Executors类中的创建线程池的方法其实就是对ThreadPoolExecutor构造函数的封装,这样就简化了参数配置,以下是Executor类的三个创建线程池的静态方法:

public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}


通过Executors类创建多线程:

 
ExecutorService pool = Executors.newFixedThreadPool(3);
Thread t1 = new Thread("lhz"){
@Override
public void run(){
System.out.println("aaa");
}
};
//把t1的run提交给线程池的某一条空闲线程
pool.submit(t1);
//可以将t1的run提交给线程池的另一条空闲线程
pool.submit(t1);
//关闭线程池
pool.shutdowm();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程池