一些小细节
应用启动初始化的时候有时候会判定下是否已经初始化过了。这个时候会设置一个变量,然后判断,然后设值。如果有概率发生并发的初始化,有可能还要加个锁。非常不简洁。下面这个方式,就让这个检查并设值的原子操作给底下来做吧,比较简洁。
if(!startFlag.compareAndSet(false, true)){return;}以前做一些并发性测试的时候用CountDownLatch挺好,对于类似CyclicBarrier只是有个功能上的大概认知。现在发现CyclicBarrier也挺不错的,关键是比较简洁。下面是一个示例,CyclicBarrier还能再促发后运行一个指定Runnable,很方便。
public class CyclicBarrierTest { public static void main(String[] args){ final CyclicBarrier cb=new CyclicBarrier(10, new Runnable() {@Overridepublic void run() {System.out.println("get here!");}}); for(int i=0;i<100;i++){ final int index=i; Thread t=new Thread(new Runnable() {@Overridepublic void run() {System.out.println("i am "+index);try {cb.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}}); t.start(); } }}结果类似每10个线程执行下Runnable
i am 0i am 9i am 7i am 5i am 3i am 1i am 13i am 11i am 4i am 2get here!i am 6i am 10i am 15i am 8i am 14i am 12i am 17i am 16i am 18i am 20get here!i am 22i am 24i am 26i am 28i am 30i am 19i am 21i am 23i am 32i am 25get here!i am 34i am 36i am 38i am 29i am 31i am 35i am 37i am 27i am 33i am 39i am 50get here!...
做一些固定EL或者特定语言(比如sql)分析的时候,常常cache一些分析过的结果,但是都用FutureTask来表示。具体这样使用的原因还需要理解,至少我看到过两个地方都是这么使用了。
/** * Compiled Expression cache */ private final static ConcurrentHashMap<String/* text expression */, FutureTask<Expression>/* * Compiled * expression * task */> cacheExpressions = new ConcurrentHashMap<String, FutureTask<Expression>>(); /** * Compile a text expression to Expression object * * @param expression * text expression * @param cached * Whether to cache the compiled result,make true to cache it. * @return */ public static Expression compile(final String expression, boolean cached) { if (expression == null || expression.trim().length() == 0) { throw new CompileExpressionErrorException("Blank expression"); } if (cached) { FutureTask<Expression> task = cacheExpressions.get(expression); if (task != null) { return getCompiledExpression(expression, task); } task = new FutureTask<Expression>(new Callable<Expression>() { public Expression call() throws Exception { return innerCompile(expression); } }); FutureTask<Expression> existedTask = cacheExpressions.putIfAbsent(expression, task); if (existedTask == null) { existedTask = task; existedTask.run(); } return getCompiledExpression(expression, existedTask); } else { return innerCompile(expression); } } private static Expression getCompiledExpression(final String expression, FutureTask<Expression> task) { try { return task.get(); } catch (Exception e) { cacheExpressions.remove(expression); throw new CompileExpressionErrorException("Compile expression failure:" + expression, e); } }分配id
private static Integer allocateId(Channel channel) { Integer id = Integer.valueOf(System.identityHashCode(channel)); for (;;) { // Loop until a unique ID is acquired. // It should be found in one loop practically. if (allChannels.putIfAbsent(id, channel) == null) { // Successfully acquired. return id; } else { // Taken by other channel at almost the same moment. id = Integer.valueOf(id.intValue() + 1); } } }