求优化-俩线程,一个读,一个写,保证原序输出

来源:互联网 发布:java 节假日api 编辑:程序博客网 时间:2024/06/05 21:50

有锁实现方案:

package com.boco.sfmhandler.bolts.sender.sort;import java.io.Serializable;import java.util.TreeMap;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicLong;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.ReentrantLock;import com.boco.sfmhandler.model.message.SMessage;/** * 只能单线程调用next *  * @author boy */public class WaitSortBlockingQueue implements SortQueue<SMessage> {private static final long serialVersionUID = -4793564853425866287L;private WaitSortBlockingQueue() {super();}private final ReentrantLock lock = new ReentrantLock(false);private final Condition empty = lock.newCondition();private final Condition full = lock.newCondition();private final AtomicLong atomicLong = new AtomicLong(0); // 初始时拿不到最小的sm的id,所以让其超时出去,并获取该id,以后进行累加private final TreeMap<Long, SMessage> map = new TreeMap<Long, SMessage>();private final int maxBlockSize = 10000;private final TimeUnit delayNanoUnit = TimeUnit.NANOSECONDS;private final long delayNanoTime = delayNanoUnit.convert(1500L,TimeUnit.MILLISECONDS); // 1.5s/** * 线程私有 */private ThreadLocal<Long> preOutputNanoTime = new ThreadLocal<Long>() {@Overrideprotected Long initialValue() {return System.nanoTime();}};public SMessage next() {long curNanoTime = System.nanoTime();final ReentrantLock lock = this.lock;SMessage sm = null;try {lock.lockInterruptibly();emptyAwait();/** * map 中保存的最小的sm的key */long firstKey;while ((firstKey = map.firstKey()) != atomicLong.get()&& ((curNanoTime = System.nanoTime()) - preOutputNanoTime.get()) < delayNanoTime) {/** * 如果firstkey < 当前累计位置,进行错误备份 这里对等待的时间没做任何修改 * 只当该sm是个过客,不影响其它sm的等待时间 */if (firstKey < atomicLong.get()) {sm = map.remove(firstKey);full.signal();failBackUp(sm);emptyAwait();continue;}long awitTime = delayNanoTime- (curNanoTime - preOutputNanoTime.get());empty.await(awitTime, delayNanoUnit);}sm = map.remove(firstKey);full.signal();atomicLong.set(firstKey + 1);setPreOutputNanoTime(curNanoTime);} catch (InterruptedException e) {empty.signal();e.printStackTrace();} finally {lock.unlock();}return sm;}/** * 如果是空,直接等待,put时会signal *  * @throws InterruptedException */private void emptyAwait() throws InterruptedException {while (map.isEmpty()) {empty.await();}}/** * 错误sm备份 *  * @param sm */private void failBackUp(SMessage sm) {}private void setPreOutputNanoTime(long nanoTime) {preOutputNanoTime.set(nanoTime);}@Overridepublic SMessage next(long timeout, TimeUnit unit) {return null;}@Overridepublic void put(long key, SMessage sm) {final ReentrantLock lock = this.lock;try {lock.lockInterruptibly();while (map.size() >= maxBlockSize)full.await();map.put(key, sm);empty.signal(); // 唤醒在next上等待的线程} catch (InterruptedException e) {full.signal();e.printStackTrace();} finally {lock.unlock();}}@Overridepublic void put(SMessage sm) {put(sm.getSortId(), sm);}private static class proxy implements Serializable {private static final long serialVersionUID = -3999942172367616131L;private final static WaitSortBlockingQueue waitSortBlockingQueue = new WaitSortBlockingQueue();}public static WaitSortBlockingQueue newInstance() {return proxy.waitSortBlockingQueue;}}


无所实现方案:(这个跳跃表貌似频繁的插入、移除有点慢,有木有更好的非阻塞、排序链表实现?)

package com.boco.sfmhandler.bolts.sender.sort;import java.util.Comparator;import java.util.concurrent.ConcurrentSkipListSet;import java.util.concurrent.TimeUnit;import com.boco.sfmhandler.model.message.SMessage;public class NoAwaitSortQueue implements SortQueue<SMessage> {private static final long serialVersionUID = -6596506016522782898L;private static final int maxSize = 10000;/** * 线程私有 */private ThreadLocal<Long> preOutputNanoTime = new ThreadLocal<Long>() {@Overrideprotected Long initialValue() {return System.nanoTime();}};private ThreadLocal<Long> index = new ThreadLocal<Long>() {@Overrideprotected Long initialValue() {return 0L;}};private ThreadLocal<Long> delayNanoTime = new ThreadLocal<Long>() {@Overrideprotected Long initialValue() {return TimeUnit.NANOSECONDS.convert(1500L, TimeUnit.MILLISECONDS); // 1.5s}};private final ConcurrentSkipListSet<SMessage> concurrentSkipListSet = new ConcurrentSkipListSet<SMessage>(new Comparator<SMessage>() {@Overridepublic int compare(SMessage o1, SMessage o2) {return Long.signum(o1.getSortId() - o2.getSortId());}});@Overridepublic void put(SMessage value) {while (concurrentSkipListSet.size() >= maxSize) {//nothing}concurrentSkipListSet.add(value);}@Overridepublic void put(long key, SMessage value) {put(value);}@Overridepublic SMessage next() {do {if (concurrentSkipListSet.isEmpty()) {continue;}SMessage sm = concurrentSkipListSet.first();long sortId = sm.getSortId();long curNanoTime = System.nanoTime();final int k = Long.signum(sortId - index.get());switch (k) {case 0:if (checkSm(sm, curNanoTime, sortId)) {return sm;}break;case -1:if (concurrentSkipListSet.remove(sm)) {failBackUp(sm);}break;case 1:if ((curNanoTime - preOutputNanoTime.get()) < delayNanoTime.get()) {continue;} else {if (checkSm(sm, curNanoTime, sortId)) {return sm;}}}} while (true);}private boolean checkSm(SMessage sm, long curNanoTime, long sortId) {boolean b = concurrentSkipListSet.remove(sm);if (b) {preOutputNanoTime.set(curNanoTime);index.set(sortId + 1);}return b;}private void failBackUp(SMessage smessage) {}@Overridepublic SMessage next(long timeout, TimeUnit unit) {return null;}private static class proxy {private static NoAwaitSortQueue noAwaitSortQueue = new NoAwaitSortQueue();}public static NoAwaitSortQueue newInstance() {return proxy.noAwaitSortQueue;}}


原创粉丝点击