线程池相关内容整理
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();
相关文章推荐
- ASP中类Class相关内容的整理资料
- ios测试相关内容整理
- Android线程池的相关内容
- 关于新版本,iOS10的相关内容,兼容iOS 10 资料整理笔记
- iOS适配的相关内容的整理
- 关于新版本,iOS10的相关内容,兼容iOS 10 资料整理笔记
- 字符串相关内容整理
- 整理浏览器相关内容
- java序列化相关内容整理
- SmsManager发短信的相关内容整理
- Intent相关内容整理
- BOM的相关内容整理
- Symbian签名和Uid相关内容的整理(一)
- DirectX学习1:整理CustomVertex类相关内容
- java正则表达式相关内容整理
- 安卓相关内容整理
- Maven相关内容收集整理-01
- Symbian 签名和Uid相关内容的整理(二)
- 广播机制相关内容整理
- 脉搏波相关概念及内容-记录整理