当前位置: 首页 > 后端技术 > Java

java并发题目的线程池很简单

时间:2023-04-01 18:40:07 Java

1。什么是线程池?我们都知道线程的创建和销毁需要一定的资源开销,这会降低计算机的整体性能。那么有没有办法避免频繁创建和销毁线程呢?基于此,引入了线程池的概念。使用线程池可以带来一系列的好处:减少资源消耗:通过池化技术重用创建的线程,减少线程创建和销毁带来的损失。改进的响应能力:当任务到达时,它会立即执行,而无需等待线程创建。提高线程的可管理性:线程是稀缺资源。如果无限制地创建它们,不仅会消耗系统资源,还会因线程分配不合理导致资源调度不平衡,降低系统稳定性。使用线程池进行统一分配、调优和监控。提供更多更强大的功能:线程池是可扩展的,允许开发者为其添加更多的功能。例如延迟定时线程池ScheduledThreadPoolExecutor,可以让任务延迟或周期性执行。2、线程池设计JDK8的线程池在Java中的核心实现类是ThreadPoolExecutor。我们先看ThreadPoolExecutor的UML类图,了解ThreadPoolExecutor的继承关系。ThreadPoolExecutor实现的顶层接口是Executor。顶层接口Executor提供了一个思路:将任务提交和任务执行解耦。用户无需关注如何创建线程以及如何调度线程执行任务。用户只需要提供Runnable对象,将任务的运行逻辑提交给Executor即可。Executor框架完成线程的部署和任务的执行。ExecutorService接口增加一些能力:(1)扩展执行任务的能力,补充可以为一个或一批异步任务生成Future的方法;(2)提供管理和控制线程池的方法,如停止线程池的运行。AbstractExecutorService是上层的一个抽象类,将执行任务的过程串联起来,保证下层的实现只需要关注一个执行任务的方法。最底层的实现类ThreadPoolExecutor实现了最复杂的运行部分。ThreadPoolExecutor一方面会维护自己的生命周期,另一方面会管理线程和任务,让两者可以很好的结合起来执行并行任务。3、线程池的实现3.1.通过Executors提供四个线程池:1.newCachedThreadPool创建一个可缓存的线程池。如果线程池长度超过处理需要,可以灵活回收线程。如果没有可回收线程,则创建一个新线程;线程池是无限的,当第一个任务执行完第二个任务时,执行第一个任务的线程会被复用,而不是创建新的线程。2、newFixedThreadPool创建一个定长线程池,可以控制最大并发线程数,超出的线程会在队列中等待;初始线程数与最大线程数相同,如果要执行的线程数大于初始线程数,则冗余线程任务加入缓存队列等待执行.3、newScheduledThreadPool创建一个支持定时和周期任务执行的定长线程池;4、newSingleThreadExecutor创建单线程线程池,只使用唯一的工作线程执行任务,保证所有任务按照指定的顺序(先进先出,后进先出,优先级)执行;Executors创建的线程池有一个致命的缺陷,在newCachedThreadPool的情况下publicclassThreadPoolDemo{publicstaticvoidmain(String[]args)throwsException{}}当我们点击进入newCachedThreadPool()方法时,我们将看到以下内容:}//我们发现第二个参数是Integer.MAX_VALUE,即最大工作线程数是Integer.MAX_VALUE。如果是超高并发,会直接OOM。所以我们必须自己通过newThreadPoolExecutor()来指定参数。3.2通过ThreadPoolExecutor创建线程池构造方法如下:publicThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,longkeepAliveTime,TimeUnitunit,BlockingQueueworkQueue,ThreadFactorythreadFactory,RejectedExecutionHandlerhandler)corePoolSize:表示核心线程数线程池,也就是最好保证的线程数。maximumPoolSize:最大线程数,也就是任务多的时候,可以工作的最大线程数。keepAliveTime:线程的空闲时间。即当实际工作线程数小于最大线程数时,部分线程处于空闲状态,当这些空闲线程的空闲时间达到keepAliveTime时,就会被杀死。但是要保证最小线程数是corePoolSize。unit:空闲时间的单位。workQueue:工作队列,即工作线程数达到corePoolSize时,任务会被放入工作队列。threadFactory:线程工厂,用于创建线程。handler:拒绝处理器,这是当工作线程达到最大工作线程,工作队列已满时,线程池应该做的事情。3.3线程池的工作流程。流程图如下:当一个任务到来时,首先判断线程池中的工作线程数是否达到核心线程数,没有则直接执行,如果是则检查工作队列是否已满。如果未满,则将任务放入工作队列,如果已满,则增加工作线程数来处理任务。如果工作线程和队列都已满,则使用指定的策略拒绝任务。3.4拒绝策略AbortPolicy(默认):直接抛出异常RejectedExecutionException,使系统无法正常运行。CallerRunsPolicy:CallerRun是一种调整机制。该策略既不放弃任务也不异常,而是将某些任务回滚给调用者,从而减少新任务的流动。DiscardOldestPolicy:丢弃队列中等待时间最长的任务,然后将当前任务加入队列并尝试再次提交当前任务。DiscardPolicy:任务直接丢弃,不处理也不抛异常。如果允许任务丢失,这是最好的解决方案。代码演示拒绝策略:1.AbortPolicypublicstaticvoidmain(String[]args)throwsException{ThreadPoolExecutorpoolExecutor=newThreadPoolExecutor(2,5,1L,TimeUnit.SECONDS,newLinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),新ThreadPoolExecutor.AbortPolicy());try{for(inti=0;i<10;i++){poolExecutor.execute(()->{System.out.println(Thread.currentThread().getName()+"\t处理业务");});}}catch(Exceptione){e.printStackTrace();}最后{poolExecutor.shutdown();}System.out.println(Thread.currentThread().getName()+"\tProcessbusiness");}即当工作线程和工作队列满时,线程池会拒绝任务并上报直接报错。2.CallerRunsPolicypublicstaticvoidmain(String[]args)throwsException{ThreadPoolExecutorpoolExecutor=newThreadPoolExecutor(2,5,1L,TimeUnit.SECONDS,newLinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),newThreadPoolExecutor.Caller());try{for(inti=0;i<10;i++){poolExecutor.execute(()->{System.out.println(Thread.currentThread().getName()+"\thandlebusiness");});}}catch(Exceptione){e.printStackTrace();}最后{poolExecutor.shutdown();}System.out.println(Thread.currentThread().getName()+"\t处理业务");}也就是说当工作线程和工作队列满了,就会把任务还给那个人谁调用线程池让他处理。3.DiscardOldestPolicy和DiscardPolicypublicstaticvoidmain(String[]args)throwsException{ThreadPoolExecutorpoolExecutor=newThreadPoolExecutor(2,5,1L,TimeUnit.SECONDS,newLinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),newThreadPoolExecutorDiscardOldestPolicy());try{for(inti=0;i<10;i++){poolExecutor.execute(()->{System.out.println(Thread.currentThread().getName()+"\thandle});}}赶上(Exceptione){e.printStackTrace();}finally{poolExecutor.shutdown();}System.out.println(Thread.currentThread().getName()+"\t处理业务");}共10个有记录输出,表示有消息被丢弃。