我有一個這樣的線程池的場景,相信不少人都遇到過:
1,每一個用戶均可以添加多個任務;
2,有不少的用戶和不少的任務;
3,每一個用戶添加的任務必須有序串行執行,即在同一時刻不能有同時執行一個用戶的兩個任務;
4,實時性:只要線程池線程有空閒的,那麼用戶提交任務後必須當即執行;儘量提升線程的利用率。
java
代碼比較簡潔,基本知足上述要求:優化
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); } } } } }
這個實現有幾個缺陷:this
1,每次添加一個任務都要進入一次鎖,有一點小小開銷;spa
2,serialJobs會一直在內存中,當某個key的任務好久沒有添加了,對應的SequentialJob對象一直存在,雖然不佔用不少內存,但對於有潔癖的人來講或,仍是不爽。線程
拋磚引玉,看看廣大網友是否能夠優化。code
(異常處理等細節你們就不要理會了)對象