洛阳市app网站开发公司电话一建论坛建工教育网

当前位置: 首页 > news >正文

洛阳市app网站开发公司电话,一建论坛建工教育网,新北区城乡建设局网站,做网站那个平台好day32 线程池 引入 一个线程完成一项任务所需时间为#xff1a; 创建线程时间 - Time1线程中执行任务的时间 - Time2销毁线程时间 - Time3 注意#xff1a;优化在Time1#xff0c;Time3(创建销毁线程费时间) 为什么需要线程池 线程池技术正是关注如何缩短或调整Time1和Tim…day32 线程池 引入 一个线程完成一项任务所需时间为 创建线程时间 - Time1线程中执行任务的时间 - Time2销毁线程时间 - Time3 注意优化在Time1Time3(创建销毁线程费时间) 为什么需要线程池 线程池技术正是关注如何缩短或调整Time1和Time3的时间从而提高程序的性能。项目中可以把Time1T3分别安排在项目的启动和结束的时间段或者一些空闲的时间段线程池不仅调整Time1Time3产生的时间段而且它还显著减少了创建线程的数目提高线程的复用率系统启动一个新线程的成本是比较高的因为涉及与操作系统的交互在这种情形下使用线程池可以很好地提高性能尤其是当程序中需要创建大量生存期很短暂的线程时优先考虑使用线程池 为什么使用线程池 1.优化并调成创建线程和销毁线程的事件 2.提高线程的复用率 3.有效控制项目中的线程目数 Java提供的线程池 ExecutorService线程池的接口 Executors创建各种线程池的工具类 理解实现了ExcutorService接口底层死循环,监视有没有提交任务所以pool.shutdown关闭 分类 1.单个线程的线程池 2.指定线程的线程池 3.可缓存线程的线程池 理解先没有线程等有任务就添加一定数量的线程去分批次执行等有线程空闲了就干掉 缺点线程目数不可控 4.延迟任务的线程池 多少时间运行一次(TimeUnit提供了很多时间单位) public class Test {public static void main(String[] args) {//创建单个线程的线程池//ExecutorService pool Executors.newSingleThreadExecutor();//创建指定线程的线程池//ExecutorService pool Executors.newFixedThreadPool(3);//创建可缓存线程的线程池自动回收60s闲置线程ExecutorService pool Executors.newCachedThreadPool();//循环创建任务对象并提交给线程池for (int i 1; i 100; i) {pool.execute(new Task(i));//提交任务i为任务编号方便理解}pool.shutdown();//关闭线程池} } class Task implements Runnable{private int i;public Task(int i) {this.i i;}Overridepublic void run() {System.out.println(Thread.currentThread().getName() – i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}} }public class Test01 {public static void main(String[] args) throws InterruptedException {//获取延迟任务的线程池ScheduledExecutorService pool Executors.newSingleThreadScheduledExecutor();//设置延迟时间时间时间单位pool.awaitTermination(6, TimeUnit.SECONDS);//循环创建任务对象并提交给线程池for (int i 1; i 100; i) {//创建任务对象Task task new Task(i);//提交任务pool.execute(task);}//关闭线程池pool.shutdown(); } } public class Task implements Runnable{private int num;public Task(int num) {this.num num;}Overridepublic void run() {System.out.println(Thread.currentThread().getName() 处理了第 num 个任务);}}深入源码 ExecutorService pool Executors.newSingleThreadExecutor(); ExecutorService pool Executors.newFixedThreadPool(3); ExecutorService pool Executors.newCachedThreadPool(); 三种线程池底层都是ThreadPoolExecutor类的对象 – 分析ThreadPoolExecutor类的构造方法源码——————————– public ThreadPoolExecutor(int corePoolSize, ————- 核心线程数量 int maximumPoolSize, ————- 最大线程数量 long keepAliveTime, ————- 闲置时间作用于核心线程数与最大线程数之间的线程TimeUnit unit, ————- keepAliveTime的时间单位(可以是毫秒、秒….)BlockingQueueRunnable workQueue, – 任务队列ThreadFactory threadFactory, ——– 线程工厂RejectedExecutionHandler handler —- 达到了线程界限和队列容量时的处理方案(拒绝策略) ) {} 执行步骤:1.创建线程池后2.任务提交后查看是否有核心线程3.1 没有 - 就创建核心线程 - 执行任务 - 执行完毕后又回到线程池中3.2 有 - 查看是否有闲置核心线程4.1 有 - 执行任务 - 执行完毕后又回到线程池4.2 没有 - 查看当前核心线程数是否核心线程数量5.1 否 - 就创建核心线程 - 执行任务 - 执行完毕后又回到线程池中5.2 是 - 查看任务列表是否装载满6.1 没有 - 就放入列表中等待出现闲置线程6.2 装满 - 查看是否有普通线程(核心线程数到最大线程数量之间的线程)7.1 没有 - 就创建普通线程 - 执行任务 - 执行完毕后又回到线程池中7.2 有 - 查看是否有闲置普通线程7.1.1 有 - 执行任务 - 执行完毕后又回到线程池中7.1.2 没有 - 查看现在所有线程数量是否为最大线程数8.1 是 - 执行处理方案默认处理抛出异常8.2 否 -就创建普通线程- 执行任务 - 执行完毕后又回到线程池中 注1.为了更好的理解在这里区分核心线程和普通线程实际上区分的这么清楚都是线程2.默认的处理方案就是抛出RejectedExecutionException 总结核心线程满载 - 任务队列 - 普通线程 - 拒绝策略– 分析单个线程的线程池的源码 ——————————– ExecutorService pool Executors.newSingleThreadExecutor(); new ThreadPoolExecutor(1, – 核心线程数量 1, – 最大线程数量 0L, – 闲置时间TimeUnit.MILLISECONDS, – 时间单位(毫秒)new LinkedBlockingQueueRunnable() – 无界任务队列可以无限添加任务 )
– 分析指定线程的线程池的源码 ——————————– ExecutorService pool Executors.newFixedThreadPool(3); new ThreadPoolExecutor(nThreads, – 核心线程数量 nThreads, – 最大线程数量 0L, – 闲置时间TimeUnit.MILLISECONDS, – 时间单位(毫秒)new LinkedBlockingQueueRunnable()– 无界任务队列可以无限添加任务 ) – 创建可缓存线程的线程池 ———————————– new ThreadPoolExecutor(0, – 核心线程数量 Integer.MAX_VALUE,– 最大线程数量 60L, – 闲置时间TimeUnit.SECONDS, – 时间单位(秒)new SynchronousQueueRunnable() – 直接提交队列(同步队列)没有容量队列任务队列详解 队列名称详解LinkedBlockingQueue无界任务队列使用无界任务队列线程池的任务队列可以无限制的添加新的任务而线程池创建的最大线程数量就是你corePoolSize设置的数量也就是说在这种情况下maximumPoolSize这个参数是无效的哪怕你的任务队列中缓存了很多未执行的任务当线程池的线程数达到corePoolSize后就不会再增加了若后续有新的任务加入则直接进入队列等待当使用这种任务队列模式时一定要注意你任务提交与处理之间的协调与控制不然会出现队列中的任务由于无法及时处理导致一直增长直到最后资源耗尽的问题SynchronousQueue 同步任务队列 直接提交任务队列使用直接提交任务队列队列没有容量每执行一个插入操作就会阻塞需要再执行一个删除操作才会被唤醒反之每一个删除操作也都要等待对应的插入操作。 任务队列为SynchronousQueue创建的线程数大于maximumPoolSize时直接执行了拒绝策略抛出异常。 使用SynchronousQueue队列提交的任务不会被保存总是会马上提交执行。如果用于执行任务的线程数量小于maximumPoolSize则尝试创建新的线程如果达到maximumPoolSize设置的最大值则根据你设置的handler执行拒绝策略。因此这种方式你提交的任务不会被缓存起来而是会被马上执行在这种情况下你需要对你程序的并发量有个准确的评估才能设置合适的maximumPoolSize数量否则很容易就会执行拒绝策略ArrayBlockingQueue有界任务队列使用有界任务队列若有新的任务需要执行时线程池会创建新的线程直到创建的线程数量达到corePoolSize时则会将新的任务加入到等待队列中。若等待队列已满即超过ArrayBlockingQueue初始化的容量则继续创建线程直到线程数量达到maximumPoolSize设置的最大线程数量若大于maximumPoolSize则执行拒绝策略。在这种情况下线程数量的上限与有界任务队列的状态有直接关系如果有界队列初始容量较大或者没有达到超负荷的状态线程数将一直维持在corePoolSize以下反之当任务队列已满时则会以maximumPoolSize为最大线程数上限。PriorityBlockingQueue优先任务队列使用优先任务队列它其实是一个特殊的无界队列它其中无论添加了多少个任务线程池创建的线程数也不会超过corePoolSize的数量只不过其他队列一般是按照先进先出的规则处理任务而PriorityBlockingQueue队列可以自定义规则根据任务的优先级顺序先后执行。 对优先队列的使用说明 public class Test {public static void main(String[] args) {ThreadPoolExecutor pool new ThreadPoolExecutor(1, 2, 1000, TimeUnit.MILLISECONDS, new PriorityBlockingQueue(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());for (int i 1; i 10; i) {pool.execute(new Task(i));}pool.shutdown();} } class Task implements Runnable,ComparableTask{private int priority;public Task(int priority) {this.priority priority;}Overridepublic void run() {try {Thread.sleep(1000);System.out.println(Thread.currentThread().getName() priority this.priority);} catch (InterruptedException e) {e.printStackTrace();}}//当前对象和其他对象做比较当前优先级大就返回-1优先级小就返回1,值越小优先级越高Overridepublic int compareTo(Task o) {return (this.priorityo.priority)?-1:1;} } 总结除了第一个任务直接创建线程执行外其他的任务都被放入了优先任务队列按优先级进行了重新排列执行且线程池的线程数一直为corePoolSize也就是只有一个。代码实现 无界队列 理解这个队列没有上限 继承关系LinkedBlockingQueue - AbstractQueue - AbstractCollection 小结 1.LinkedBlockingQueue是Collection集合家族的一员 2.Collection集合家族List、Set、Queue 3.LinkedBlockingQueue数据结构单向链表 缺点LinkedBlockingQueue可能造成内存溢出 有界队列 继承关系ArrayBlockingQueue - AbstractQueue - AbstractCollection 小结 1.ArrayBlockingQueue是Collection集合家族的一员 2.Collection集合家族List、Set、Queue 3.ArrayBlockingQueue数据结构一维数组 public class Test01 {public static void main(String[] args) throws InterruptedException {//创建无界队列LinkedBlockingQueueString queue new LinkedBlockingQueue();//创建有界队列//ArrayBlockingQueueString queue new ArrayBlockingQueue(6);//添加元素queue.put(aaa);queue.put(bbb);queue.put(ccc);queue.put(ddd);queue.put(eee);queue.put(fff);//删除元素queue.remove(ccc);//遍历队列IteratorString it queue.iterator();while (it.hasNext()) {String string it.next();System.out.println(string);} } }优先队列 继承关系ArrayBlockingQueue - AbstractQueue - AbstractCollection 小结 1.ArrayBlockingQueue是Collection集合家族的一员 2.Collection集合家族List、Set、Queue 3.ArrayBlockingQueue数据结构一维数组 public class Test03 {public static void main(String[] args) throws InterruptedException {//创建优先队列PriorityBlockingQueueTask queue new PriorityBlockingQueue();//无参构造底层使用的是元素的内置比较器//添加元素queue.add(new Task(3));queue.add(new Task(1));queue.add(new Task(4));queue.add(new Task(2));//遍历取出队列while(!queue.isEmpty()){//删除第一元素Task poll queue.poll();System.out.println(poll.getPriority());}} }Task类 public class Task implements Runnable,ComparableTask{private int priority;//优先级别public Task(int priority) {this.priority priority;}Overridepublic void run() {System.out.println(任务被处理了);}//当前对象和其他对象做比较当前优先级大就返回-1优先级小就返回1,值越小优先级越高Overridepublic int compareTo(Task o) {return Integer.compare(this.priority, o.priority);}public int getPriority() {return priority;} } 总结 1.Java自带的线程池 单个线程的线程池 指定线程个数的线程池 可缓存的线程池 延迟任务的线程池 2.线程池的7大参数 核心线程数 最大线程数 任务队列有界、无界、同步、优先队列 拒绝策略 闲置时间 时间单位 线程工厂 3.线程池的调用步骤核心线程、任务队列、普通线程、拒绝策略 4.任务队列及底层原理有界、无界、同步、优先队列