线程池 今天药忘吃喽~ 2022-05-28 03:41 35阅读 0赞 ## 为什么要使用线程池 ## 在多线程环境中,不断地创建和销毁线程既耗时又耗费系统资源。为了提高程序的性能,并发包提供了线程池来管理多线程。它的基本原理是仅仅创建数量有限的线程,每个线程都会持续不断地执行各种任务。 ## 线程池相关接口和类 ## 并发包中与线程池相关的类和接口 ![这里写图片描述][SouthEast] **1. Executor接口** Executor接口表示线程池,它只有一个execute()方法,用来执行线程中run()方法中的任务,线程池会调度空闲的线程来执行任务。 **2. ExecutorService接口** ExecutorService接口是Executor的子接口,它具有管理线程池的一些方法: * shutdown():预备关闭线程。如果已有任务开始执行,那么要等这些任务执行完毕后,才会去关闭线程。 * shutdownNow():终止已经开始的任务,立刻关闭线程。 * awaitTermination():等待线程池关闭。 * isTerminated():判断线程池是否关闭,如果关闭,返回true;否则返回false。 方法`submit(Runnable task)`和`submit(Callable<T> task)`作用与Executor接口的execute(Runnable command)方法相似,都用于向线程池提交任务。区别在于前两个方法支持异步运算,他们会返回表示异步运算结果的Future对象。 **3. Executors类** * newCachedThreadPool():创建拥有缓存的线程池。有任务时才创建线程,空闲的线程在线程池中被保留60秒。 * newFixedThreadExecutor(int nTreads):创建拥有固定数目线程的线程池。空闲的线程池会一直保留。参数nThreads用来设定线程池线程的数目。 * newSingleThreadExecutor():创建只有一个线程的线程池。这单个线程会依次执行每个任务。如果这个线程因为异常而终止,不会重新创建替代它的线程,这是与newFixedThreadExecutor(1)方法的不同之处。newFixedThreadExecutor(1)尽管也是之创建一个线程,但是如果这个线程因为异常终止,线程池会重新创建一个新的线程来替代它继续执行任务。 * newScheduleThreadPool(int corePoolSize):线程池会按时间计划来执行任务,允许用户设定计划执行任务的时间。参数corePoolSize设定线程池中的线程的最小数目。当任务较多时,线程池可能会创建更多的线程来执行任务。 * newSingleThreadScheduleExecutor():创建一个只有线程的线程池。这一个线程能按照时间计划来执行任务。 public class Machine implements Runnable{ private int id; public Machine(int id){ this.id = id; } @Override public void run() { for(int i = 0;i < 10;i++){ System.out.println("当前线程: " + Thread.currentThread().getName() + " 当前Machine" + id + ":i = " + i); Thread.currentThread().yield(); } } public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(2); for(int i = 0;i < 5;i++){ executorService.execute(new Machine(i)); //executorService.submit(new Machine(i)); } System.out.println("任务提交结束"); executorService.shutdown(); System.out.println("等待已提交的任务完成后,服务关闭"); } } ## 阻塞队列BlockingQueue ## 当多个线程操作同一个队列时,会导致并发问题。BolckingQueue接口为多个线程操作同一队列提供了4中处理方案。 1. 抛出异常。 2. 返回特定值。在队尾添加元素时,如果队列已满,返回false。对头删除或读取元素,如果队列为空,返回null。 3. 线程阻塞。 4. 超时。 **BlockingQueue 任务缓存队列和排队策略** 用来存放任务的缓存队列,有以下子类,通常LinkedBlockingQueue使用较多。 * LinkedBlockingQueue类:默认情况下,LinkedBlockingQueue的容量是没有上限的,但是也可以选择指定其容量大小。它是基于链表的队列,此队列按FIFO原则存取元素。 * ArrayBlockingQueue类:它的构造方法允许指定队列容量大小,并可以选择是否采用公平策略。如果参数fair被设为true,那么等待时间最长的线程会优先访问队列,其底层是通过将ReentrantLock设置为公平锁的策略来达到的。ArrayBlockingQueue是基于数组的队列,他也是按照FIFO原则存取数据。 * PriorityBlockingQueue类:一个带优先级的队列。元素按照优先级的顺序来删除,该队列的容量没有上限。 * DelayQueue类:这个队列中放的是延迟元素。 **任务拒绝策略** 当线程池的任务缓存队列已满并且线程池的线程数量已经达到maximumPoolSize,如果还有任务到来,就采取任务拒绝策略,通常有以下4种策略: * ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 * ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 * ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程) * ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 [SouthEast]: /images/20220528/b10df470e4d448e7b78071814e2b5f5c.png
相关 Java 线程池、Runnable线程池、Callable线程池 线程池: 其实就是一个容纳多个线程的容器,其中的线程可以反复的使用,省去了频繁创建和销毁过程对象的操作,无需反复创建线程面消耗过多资源。 为什么要用线程池: 合理 青旅半醒/ 2023年02月26日 12:30/ 0 赞/ 50 阅读
相关 线程、线程池 创建线程的3种方法: package com.frank.threadPool.createThread; / @author 小石潭记 布满荆棘的人生/ 2022年10月22日 04:27/ 0 赞/ 384 阅读
相关 线程池 1.所谓线程池,就是程序的初始化阶段,就预先创建一批线程,每个线程都做好准备干活; 2.然后有一个任务列表,一开始为空,当有任务来了,就往任务列表里面添加;这个任务列表 痛定思痛。/ 2022年06月13日 13:22/ 0 赞/ 328 阅读
相关 线程池 西施越溪女,明艳光云海 最近用线程池和不用线程池做了个速度的测试,在这里备注下: 结果是速度不相上下; public static void main(Str 妖狐艹你老母/ 2022年05月20日 02:35/ 0 赞/ 282 阅读
相关 线程池 线程池 Java里面线程池的顶级接口是 java.util.concurrent.Executor , 但是严格意义上讲 Executor并不是一个线程池,而只是一个 迈不过友情╰/ 2022年03月06日 14:34/ 0 赞/ 400 阅读
相关 线程池 线程池 > 从字面义上来讲,是指管理一组同构工作线程的资源池。线程池是与工作队列密切相关的,其中在工作队列中(Worker Queue)保存了所有等待执行的任务。工作者( 清疚/ 2021年12月11日 03:35/ 0 赞/ 388 阅读
相关 线程池 可preStart一个或全部core thread 0,小于core则来一个任务建一个线程(firstTask),队列,额外线程,拒绝 一个AtomicInteger的 今天药忘吃喽~/ 2021年11月23日 03:40/ 0 赞/ 412 阅读
相关 线程池 1、先创建线程池 import java.util.concurrent.ArrayBlockingQueue; import java.util.concu 拼搏现实的明天。/ 2021年11月09日 14:28/ 0 赞/ 422 阅读
还没有评论,来说两句吧...