|
目录线程池拒绝策略概述1.AbortPolicy(默认策略)2.CallerRunsPolicy3.DiscardPolicy4.DiscardOldestPolicy5.自定义拒绝策略在Java多线程编程中,线程池(ThreadPool)是一种重要的并发工具,它允许我们创建一组可复用的线程来执行多个任务。然而,当线程池中的线程数达到其最大容量,并且任务队列也满了时,新提交的任务就需要被处理,这时就会用到线程池的拒绝策略。本文将详细介绍Java中ThreadPoolExecutor提供的四种拒绝策略,并探讨它们的特点、使用场景及示例代码。线程池拒绝策略概述线程池的拒绝策略是指当线程池无法接受新任务时,如何处理这些被拒绝的任务。ThreadPoolExecutor提供了四种内置的拒绝策略,并且允许用户自定义拒绝策略。1.AbortPolicy(默认策略)特点:当任务无法被线程池执行时,会抛出一个RejectedExecutionException异常。使用场景:适用于对任务丢失敏感的场景,当线程池无法接受新任务时,希望立即知道并处理该异常。示例代码:importjava.util.concurrent.*;publicclassAbortPolicyDemo{publicstaticvoidmain(String[]args){ThreadPoolExecutorexecutor=newThreadPoolExecutor(2,2,0L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue(2),newThreadPoolExecutor.AbortPolicy());for(inti=0;i{System.out.println("Task"+Thread.currentThread().getName()+"isrunning.");try{Thread.sleep(1000);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}});}executor.shutdown();}}12345678910111213141516171819202122232.CallerRunsPolicy特点:当任务无法被线程池执行时,会直接在调用者线程中运行这个任务。如果调用者线程正在执行一个任务,则会创建一个新线程来执行被拒绝的任务。使用场景:适用于可以容忍任务在调用者线程中执行的业务场景,它允许任务继续执行,而不会因为线程池资源不足而被丢弃。示例代码:importjava.util.concurrent.*;publicclassCallerRunsPolicyDemo{publicstaticvoidmain(String[]args){ThreadPoolExecutorexecutor=newThreadPoolExecutor(2,2,0L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue(2),newThreadPoolExecutor.CallerRunsPolicy());for(inti=0;i{System.out.println("Task"+Thread.currentThread().getName()+"isrunning.");try{Thread.sleep(1000);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}});}executor.shutdown();}}12345678910111213141516171819202122233.DiscardPolicy特点:当任务无法被线程池执行时,任务将被直接丢弃,不抛出异常,也不执行任务。使用场景:适用于对任务丢失不敏感的场景,当线程池无法接受新任务时,简单地丢弃被拒绝的任务。示例代码:importjava.util.concurrent.*;publicclassDiscardPolicyDemo{publicstaticvoidmain(String[]args){ThreadPoolExecutorexecutor=newThreadPoolExecutor(2,2,0L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue(2),newThreadPoolExecutor.DiscardPolicy());for(inti=0;i{System.out.println("Task"+Thread.currentThread().getName()+"isrunning.");try{Thread.sleep(1000);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}});}executor.shutdown();}}12345678910111213141516171819202122234.DiscardOldestPolicy特点:当任务无法被线程池执行时,线程池会丢弃队列中最旧的未处理任务,然后尝试重新提交当前任务。使用场景:适用于对新任务优先级较高的场景,当线程池无法接受新任务时,会丢弃一些等待时间较长的旧任务,以便接受新任务。示例代码:importjava.util.concurrent.*;publicclassDiscardOldestPolicyDemo{publicstaticvoidmain(String[]args){ThreadPoolExecutorexecutor=newThreadPoolExecutor(2,2,0L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue(2),newThreadPoolExecutor.DiscardOldestPolicy());for(inti=0;i{System.out.println("Executingtask"+taskId+"by"+Thread.currentThread().getName());try{Thread.sleep(1000);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}});}executor.shutdown();//等待所有任务完成(尽管有些任务可能已被丢弃)try{if(!executor.awaitTermination(5,TimeUnit.SECONDS)){executor.shutdownNow();}}catch(InterruptedExceptione){executor.shutdownNow();Thread.currentThread().interrupt();}}}123456789101112131415161718192021222324252627282930313233在这个例子中,我们尝试提交了5个任务到一个容量为2的线程池,其中任务队列的最大容量也设置为2。由于DiscardOldestPolicy被用作拒绝策略,当尝试提交第5个任务时,队列中最旧的任务(即第1个任务)将被丢弃,然后尝试重新提交当前任务(但在这个例子中,由于线程池和队列都已满,第5个任务实际上也会被丢弃,因为没有额外的空间来容纳它)。5.自定义拒绝策略除了上述四种内置的拒绝策略外,ThreadPoolExecutor还允许你通过实现RejectedExecutionHandler接口来定义自己的拒绝策略。这提供了极高的灵活性,可以根据具体需求定制拒绝任务的行为。自定义拒绝策略示例:importjava.util.concurrent.*;publicclassCustomRejectionPolicyimplementsRejectedExecutionHandler{@OverridepublicvoidrejectedExecution(Runnabler,ThreadPoolExecutorexecutor){//在这里定义你的自定义处理逻辑System.out.println("Task"+r.toString()+"wasrejected");//可以选择记录日志、抛出异常、使用备用线程池执行等}publicstaticvoidmain(String[]args){ThreadPoolExecutorexecutor=newThreadPoolExecutor(2,2,0L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue(2),newCustomRejectionPolicy());//提交任务...}}12345678910111213141516171819在自定义拒绝策略中,你可以访问被拒绝的任务(Runnabler)和线程池实例(ThreadPoolExecutorexecutor),从而可以根据这些信息来做出决策,比如记录日志、抛出异常、将任务提交到另一个线程池等。线程池拒绝策略是处理超出线程池处理能力的任务的一种方式。Java提供了四种内置的拒绝策略,每种策略都有其适用场景。然而,在复杂的应用场景中,这些内置策略可能无法满足需求,此时可以通过实现自定义拒绝策略来灵活处理。无论是使用内置策略还是自定义策略,都需要根据应用的具体需求和资源状况来合理选择,以确保系统的稳定性和高效性。在设计系统时,合理配置线程池的大小、任务队列的容量以及选择合适的拒绝策略,对于提高系统的并发处理能力和稳定性至关重要。
|
|