我有一个这样的线程池的场景,相信很多人都遇到过:
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对象一直存在,虽然不占用很多内存,但对于有洁癖的人来说或,还是不爽。
抛砖引玉,看看广大网友是否可以优化。
(异常处理等细节大家就不要理会了)
相关推荐
当异步执行的任务需要保证顺序性时,可以使用线程锁来保证任务的串行执行。通过在线程池中初始化一个线程锁对象,确保当一个任务在执行时,其他任务需要等待,直到锁被释放。这种机制可以用于防止对共享资源的竞争...
在实际应用中,我们可能需要根据业务需求动态地配置定时任务的执行方式,例如,某些任务可能需要串行执行,而其他任务则可以并行处理。本篇文章将深入探讨如何利用Quartz实现定时任务的分组、串行和并行动态配置。 ...
1. newSingleThreadExecutor():创建一个单线程的线程池,保证任务按提交顺序串行执行。 2. newFixedThreadPool(int nThreads):创建一个固定大小的线程池,池中维护着指定数量的工作线程,一旦工作线程因执行任务...
串行线程池是指一个线程池中只有一个线程在执行任务,其他线程在队列中等待执行。这和并发线程池不同,后者可以同时执行多个线程。 为了实现一个串行的线程池,我们需要使用Java提供的ThreadPoolExecutor类。...
- `newSingleThreadExecutor()`:创建单线程的线程池,所有任务在线程池中串行执行。 示例: ```java ExecutorService executorService = Executors.newFixedThreadPool(3); for (int i = 0; i ; i++) { ...
这个主题主要涉及如何将原本设计为并行运行的任务转换为串行执行,以适应某些特定场景的需求或解决特定问题。CGLIB(Code Generation Library)是一个在Java平台上的动态代理库,它被广泛用于AOP(面向切面编程)和...
3. **SingleThreadExecutor**: `Executors.newSingleThreadExecutor()`创建一个只有一个线程的线程池,所有任务都会按照提交的顺序串行执行。这个线程池适用于需要保证执行顺序的场景,比如日志记录或者数据库事务。...
单线程的线程池是指只有一个线程在工作的线程池,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。 ...
- 特点:只有一个工作线程,确保所有任务按顺序执行,任务之间具有串行化特性。 - 优点:保证任务执行的顺序性,适用于需要保持任务执行顺序的场景。 - 缺点:并发处理能力弱,只适用于轻量级任务,且无法利用...
通过将原本顺序执行的任务分解为多个子任务,然后并发地执行这些子任务,可以显著提高程序运行效率。CGLIB(Code Generation Library)作为一款强大的Java字节码操作库,常常被用来实现这一目标。 CGLIB是一个高...
2. 单线程池:`Executors.newSingleThreadExecutor()`,只有一个线程,任务按顺序执行,确保任务间的串行化。 3. 定时线程池:`Executors.newScheduledThreadPool(int corePoolSize)`,支持定时及周期性任务,可用于...
2. 高效执行:汇编语言编写程序通常执行速度更快,适合实时性要求高的串行通信任务。 3. 详细控制:汇编语言可以精确控制每个步骤,如设置波特率、数据格式和握手协议等。 微机原理与串行通信接口: 1. 8251A UART...
Spring定时任务(Scheduler)的串行、并行执行实现解析 Spring Framework提供了一个强大的任务调度器(Scheduler),可以用于实现各种类型的定时任务。其中,串行执行和并行执行是两种常见的任务执行模式。本文将...
单片机C语言程序设计 2×20串行字符液晶演示(有源码)单片机C语言程序设计 2×20串行字符液晶演示(有源码)单片机C语言程序设计 2×20串行字符液晶演示(有源码)单片机C语言程序设计 2×20串行字符液晶演示(有源码)...
- `newSingleThreadExecutor()`:创建一个单线程的线程池,所有的任务都会被串行执行。 - `newScheduledThreadPool(int corePoolSize)`:创建一个定长线程池,支持定时及周期性任务执行。 使用ExecutorService时,...
- **串行任务执行**:在一个串行队列中,即使任务是异步提交的,也会按照添加的顺序依次执行。 - **并发任务执行**:在并行队列中,多个任务可以并发执行,但要注意资源竞争问题。 ### **4. 依次执行任务** - ...
2. **SingleThreadExecutor**:单线程的线程池,所有的任务都会在唯一的工作线程中顺序执行,保证了执行顺序的串行性。 3. **CachedThreadPool**:缓存线程池,会为每个任务创建新的线程,如果线程池中存在空闲线程...
5. 串行通信发射机的设计和实现:串行通信发射机的设计和实现需要考虑到系统的任务分析、电路设计、软件设计和测试等方面。 本设计基于单片机的串行通信发射机的设计与实现,为解决串行通信中的数据可靠性问题提供...
51单片机,尤其是89C51型号,是单片机领域的经典选择,其串行接口具有重要的应用价值。 串行通信是一种数据传输方式,相较于并行通信,它只需要两根信号线(数据线和地线)就能实现数据传输,因此成本更低,适合远...
双机串行通信系统设计是计算机接口技术课程设计...总的来说,这个双机串行通信系统设计项目涵盖了串行通信协议、接口芯片应用、中断处理机制等多个关键知识点,对于提升学生的硬件设计能力和实践操作技能具有显著作用。