java线程池工作队列饱和策略代码示例

2025-05-29 0 57

线程池(thread pool) 是并行执行任务收集的实用工具。随着 cpu 引入适合于应用程序并行化的多核体系结构,线程池的作用正日益显现。通过 threadpoolexecutor类及其他辅助类,java 5 引入了这一框架,作为新的并发支持部分。

threadpoolexecutor框架灵活且功能强大,它支持特定于用户的配置并提供了相关的挂钩(hook)和饱和策略来处理满队列

java线程池会将提交的任务先置于工作队列中,在从工作队列中获取(synchronousqueue直接由生产者提交给工作线程)。那么工作队列就有两种实现策略:无界队列和有界队列。无界队列不存在饱和的问题,但是其问题是当请求持续高负载的话,任务会无脑的加入工作队列,那么很可能导致内存等资源溢出或者耗尽。而有界队列不会带来高负载导致的内存耗尽的问题,但是有引发工作队列已满情况下,新提交的任务如何管理的难题,这就是线程池工作队列饱和策略要解决的问题。

饱和策略分为:abort 策略, callerruns 策略,discard策略,discardolds策略。

为了更好的理解,我编写一个小的例子。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50
package concurrency.pool;

import java.util.concurrent.linkedblockingdeque;

import java.util.concurrent.rejectedexecutionhandler;

import java.util.concurrent.threadpoolexecutor;

import java.util.concurrent.timeunit;

public class saturationpolicy {

/**

* 线程池工作队列已满时,在不同饱和策略下表现

* @param handler 线程池工作队列饱和策略

*/

public static void policy(rejectedexecutionhandler handler){

//基本线程2个,最大线程数为3,工作队列容量为5

threadpoolexecutor exec = new threadpoolexecutor(2,3,0l, timeunit.milliseconds,new linkedblockingdeque<>(5));

if (handler != null){

exec.setrejectedexecutionhandler(handler);

//设置饱和策略

}

for (int i = 0; i < 10; i++) {

exec.submit(new task());

//提交任务

}

exec.shutdown();

}

public static void main(string[] args) {

// policy(new threadpoolexecutor.abortpolicy());

// policy((new threadpoolexecutor.callerrunspolicy()));

// policy(new threadpoolexecutor.discardpolicy());

// policy(new threadpoolexecutor.discardoldestpolicy());

}

//自定义任务

static class task implements runnable {

private static int count = 0;

private int id = 0;

//任务标识

public task() {

id = ++count;

}

@override

public void run() {

try {

timeunit.seconds.sleep(3);

//休眠3秒

}

catch (interruptedexception e) {

system.err.println("线程被中断" + e.getmessage());

}

system.out.println(" 任务:" + id + "\\t 工作线程: "+ thread.currentthread().getname() + " 执行完毕");

}

}

}

当工作队列满了,不同策略的处理方式为:

1.abort策略:默认策略,新任务提交时直接抛出未检查的异常rejectedexecutionexception,该异常可由调用者捕获。
在主函数中添加如下代码:

?

1
policy(new threadpoolexecutor.abortpolicy());

运行结果为:

java线程池工作队列饱和策略代码示例

程序抛出了rejectedexecutionexception,并且一共运行了8个任务(线程池开始能运行3个任务,工作队列中存储5个队列)。当工作队列满了的时候,直接抛出了异常,而且jvm一直不退出(我现在也不知道什么原因)。我们可以看到执行任务的线程全是线程池中的线程。

2.callerruns策略:为调节机制,既不抛弃任务也不抛出异常,而是将某些任务回退到调用者。不会在线程池的线程中执行新的任务,而是在调用exector的线程中运行新的任务。

在主函数运行:

?

1
policy((new threadpoolexecutor.callerrunspolicy()));

运行结果

java线程池工作队列饱和策略代码示例

所有的任务都被运行,且有2(10 – 3 -5)个任务是在main线程中执行成功的,8个任务在线程池中的线程执行的。
3.discard策略:新提交的任务被抛弃。
在main函数中运行

?

1
policy(new threadpoolexecutor.discardpolicy());

java线程池工作队列饱和策略代码示例

通过上面的结果可以显示:没有异常抛出,后面提交的2个新任务被抛弃,只处理了前8(3+5)个任务,jvm退出。

4.discardoldest策略:队列的是“队头”的任务,然后尝试提交新的任务。(不适合工作队列为优先队列场景)

在main函数中运行如下方法

?

1
policy(new threadpoolexecutor.discardoldestpolicy());

运行结果:一共运行8个任务,程序结束,后面添加的任务9,任务10被执行了,而前面的任务3,任务4被丢弃。

java线程池工作队列饱和策略代码示例

总结

以上就是本文关于java线程池工作队列饱和策略代码示例的全部内容,希望对大家有所帮助。如有不足之处,欢迎留言指出。感谢朋友们对本站的支持。

原文链接:http://blog.csdn.net/lixwjava/article/details/51813032

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 java线程池工作队列饱和策略代码示例 https://www.kuaiidc.com/113895.html

相关文章

发表评论
暂无评论