package com.sissi.looper.impl; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Random; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.sissi.commons.Trace; import com.sissi.feed.Feeder; import com.sissi.looper.Looper; import com.sissi.looper.LooperBuilder; import com.sissi.resource.ResourceCounter; import com.sissi.thread.Runner; import com.sissi.thread.impl.ExecuteInterval; /** * 公共Loop策略,所有Loop共享公共线程 * * @author kim 2014年4月14日 */ public class GlobalLooperBuilder implements Looper, LooperBuilder, Runnable { private final String resource = GlobalLooperBuilder.class.getSimpleName(); /** * TODO: 优化随机删除 */ private final List<GlobalLooper> loopers = new ArrayList<GlobalLooper>(); private final Random random = new Random(new Date().getTime()); private final Log log = LogFactory.getLog(this.getClass()); private final AtomicBoolean state = new AtomicBoolean(); /** * 计数器 */ private final AtomicLong next = new AtomicLong(); private final ResourceCounter resourceCounter; private final ExecuteInterval interval; private final int threadNum; /** * @param runner * @param interval 堵塞时间 * @param threadNum 线程数量 * @param resourceCounter */ public GlobalLooperBuilder(Runner runner, ExecuteInterval interval, int threadNum, ResourceCounter resourceCounter) { super(); this.start(); this.interval = interval; this.threadNum = threadNum; this.resourceCounter = resourceCounter; runner.executor(threadNum, this); } @Override public GlobalLooper build(Future<?> future, Feeder feeder) { return new GlobalLooper(future, feeder); } @Override public GlobalLooperBuilder start() { this.state.set(true); return this; } @Override public GlobalLooperBuilder stop() { this.state.set(false); return this; } @Override public void run() { this.resourceCounter.increment(this.resource); while (true) { try { if (!this.state.get()) { break; } int mod = this.loopers.size(); if (mod > 0) { this.getAndFeed(mod); } else { // TODO: change to wait(); Thread.sleep(this.interval.convert(TimeUnit.MILLISECONDS) * this.random.nextInt(this.threadNum)); } } catch (Exception e) { this.log.warn(e.toString()); Trace.trace(this.log, e); } } this.resourceCounter.decrement(this.resource); } /** * 取值范围为顺序0-looper.size() * * @param mod * @throws Exception */ private void getAndFeed(int mod) throws Exception { GlobalLooper looper = this.loopers.get((int) (this.next.incrementAndGet() % mod)); // Double check if (looper != null) { looper.getAndFeed(); } } private class GlobalLooper extends FeedLooper { public GlobalLooper(Future<?> future, Feeder feeder) { super(GlobalLooperBuilder.this.interval, future, feeder); } @Override public GlobalLooper start() { GlobalLooperBuilder.this.loopers.add(this); return this; } @Override public GlobalLooper stop() { GlobalLooperBuilder.this.loopers.remove(this); return this; } } }