文档章节

具有相同属性任务串行有序执行的线程池设计

BlackJoker
 BlackJoker
发布于 2015/10/13 13:24
字数 411
阅读 34
收藏 0

我有一个这样的线程池的场景,相信很多人都遇到过: 
1,每个用户都可以添加多个任务; 
2,有很多的用户和很多的任务; 
3,每个用户添加的任务必须有序串行执行,即在同一时刻不能有同时执行一个用户的两个任务; 
4,实时性:只要线程池线程有空闲的,那么用户提交任务后必须立即执行;尽可能提高线程的利用率。 

代码比较简洁,基本满足上述要求:

public class SerialThreadExecutor {
	private Executor executor;
	private ConcurrentMap<Object, SequentialJob> serialJobs = new ConcurrentHashMap<Object, SequentialJob>();

	public SerialThreadExecutor(Executor executor) {
		super();
		this.executor = executor;
	}

	public void executeSerially(Object key, Runnable r) {
		SequentialJob job = serialJobs.get(key);
		if (job == null) {
			job = new SequentialJob(key);
			SequentialJob oldJob = serialJobs.put(key, job);
			if (oldJob != null) {
				job = oldJob;
			}
		}
		job.addJob(r);
	}

	private class SequentialJob implements Runnable {
		private BlockingQueue<Runnable> jobs = new LinkedBlockingQueue<Runnable>();
		private Object key;
		private AtomicBoolean running = new AtomicBoolean(false);

		public SequentialJob(Object key) {
			this.key = key;
		}

		public void run() {
			Runnable r = null;
			while (true) {
				try {
					r = jobs.poll(50, TimeUnit.MILLISECONDS);
					if (r != null) {
						r.run();
					} else {
						synchronized (this) {
							if (jobs.isEmpty()
									&& running.compareAndSet(true, false)) {
								return;
							} else {
								continue;
							}
						}
					}
				} catch (InterruptedException e) {
					// TODO
					e.printStackTrace();
				}
			}
		}

		public void addJob(Runnable r) {
			synchronized (this) {
				jobs.add(r);
				if (running.compareAndSet(false, true)) {
					executor.execute(this);
				}
			}
		}
	}
}

这个实现有几个缺陷:

1,每次添加一个任务都要进入一次锁,有一点小小开销;

2,serialJobs会一直在内存中,当某个key的任务很久没有添加了,对应的SequentialJob对象一直存在,虽然不占用很多内存,但对于有洁癖的人来说或,还是不爽。

 

抛砖引玉,看看广大网友是否可以优化。

(异常处理等细节大家就不要理会了)

 

© 著作权归作者所有

共有 人打赏支持
BlackJoker
粉丝 1
博文 17
码字总数 9270
作品 0
深圳
高级程序员
私信 提问
源码|从串行线程封闭到对象池、线程池

今天讲一个牛逼而实用的概念,。是串行线程封闭的典型应用场景;糅合了对象池技术,但核心实现不依赖于对象池,很容易产生误会。本文从串行线程封闭和对象池入手,最后通过源码分析线程池的核...

猴子007
2017/11/14
0
0
JAVA线程池以及队列拒绝策略

工作中遇到了消息队列的发送,之前都是用数据库作为中转和暂存的。这次考虑用多线程的方式进行消息的发送,于是学习了一下线程池的应用。说实话,实践中对Java高级特性的应用真的不多,对多线...

健康的程序员
2016/05/17
73
0
Java并发编程之线程池必用知识点

再使用线程池之前,我们应该了解为什么需要使用线程池。进行执行任务(task)的时候我们一般情况是new Thread进行执行,如果进行大量的并发任务的时候呢? 大多数并发应用程序是围绕执行任务...

静默加载
2017/10/11
0
0
【iOS】Swift4.0 GCD的使用笔记

前言 在Swift4.0版本中GCD的常用方法还是有比较大的改动,这里做个简单的整理汇总。 GCD的队列 队列是一种遵循先进先出(FIFO)原则的数据结构,是一种特殊的线性表。 X 表示禁止这么使用,—...

Roki_Liu
03/21
0
0
java并发编程——线程池和Executor介绍

第一部分:概述 早期的应用程序大多是单线程串行执行的,虽然程序的任务边界清晰有序,但是执行的效率却很低,尤其是执行花费时间较长的操作,会导致大量的等待和堆积。为了提高程序的执行效...

isam
2016/05/26
91
0

没有更多内容

加载失败,请刷新页面

加载更多

Flink-数据流编程模型

1、抽象等级 Flink提供了不同级别的抽象来开发流/批处理应用程序。 1) 低层级的抽象 最低层次的抽象仅仅提供有状态流。它通过Process函数嵌入到DataStream API中。它允许用户自由地处理来自一...

liwei2000
24分钟前
1
0
Java开发Swing实战JFrame和JTabbedPane容器的用法详细解析

概述: 项目是一个桌面程序,涉及标签和按钮组件、布局管理器组件、面板组件、列表框和下拉框组件等组件,以及Swing事件处理机制。 下面先从最基础的界面开始。 /** * @author: lishuai * @...

金铭鼎IT教育
29分钟前
9
0
flask 之旅

环境 为了正确地跑起来,你的应用需要依赖许多不同的软件。 就算是再怎么否认这一点的人,也无法否认至少需要依赖Flask本身。 你的应用的运行环境,在当你想要让它跑起来时,是至关重要的。 ...

hblt-j
29分钟前
6
0
easyui的上传文件

记录一下自己亲手操刀easyui的心得:不用不知道,一用就问题多,网上查资料,有用的真的太少了 ——————————————————正文 FileBox,还是不错的讲真,至少我去自己写就gaga了...

anlve
31分钟前
4
0
如何做好SQLite 使用质量检测,让事故消灭在摇篮里

本文由云+社区发表 SQLite 在移动端开发中广泛使用,其使用质量直接影响到产品的体验。 常见的 SQLite 质量监控一般都是依赖上线后反馈的机制,比如耗时监控或者用户反馈。这种方式问题是: ...

腾讯云加社区
33分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部