简介

java.util.concurrent包是Java 5的一个重大改进,java.util.concurrent包提供了多种线程间同步和通信的机制,比如Executors, Queues, Timing, Synchronizers和Concurrent Collections等。与synchronized关键字和Object.notify()等方法相比,这些类和方法的抽象层次都较高。Effective Java中提到,其中比较重要的同步和通信机制有Executor框架、Concurrent Collections和Synchronizers三种。

其中Synchronizers包含了五种: Semaphore信号量,CounDownLatch倒计时锁存器,CyclicBarrier循环栅栏,Phaser和Exchanger。 JCIP中提到,Exchanger可以看做一种特殊的Barrier。Effective Java 提到用的比较多的主要是Semaphore信号量和CounDownLatch倒计时锁存器。本文主要讲解我认为比较重要的Semaphore信号量、CounDownLatch计数锁存器和CyclibBarrier。每一种都按照它们的概念、jdk实现、所提供的方法和使用(traveler或者jdk, or sample code)来进行介绍。

1 Semaphore

semaphore,信号量,是众多synchronizer中的一个。在操作系统中就存在互斥量和信号量这样的概念。 semaphore跟锁机制存在一定的相似性,semaphore也是一种锁机制,所不同的是,reentrantLock是只允许一个线程获得锁,而信号量持有多个许可(permits),允许多个线程获得许可并执行。从这个意义上看,重入锁是许可只有1的信号量。它们所提供的方法也非常接近。

1.1 实现

跟ReentrantLock一样,Semaphore也是以AQS为基础来实现的。

1.1.1 构造函数:

非公平版本:

1     public Semaphore(int permits) {
2 sync = new NonfairSync(permits);
3 }

可以选择是否公平的版本:

1     public Semaphore(int permits, boolean fair) {
2 sync = fair ? new FairSync(permits) : new NonfairSync(permits);
3 }

1.1.2 其他方法

跟ReentrantLock不同的是,每种acquire方法都分为有参数的和不带参数的两个版本:
acquire() :

1     public void acquire() throws InterruptedException {
2 sync.acquireSharedInterruptibly(1);
3 }

acquire(int permits)

1     public void acquire(int permits) throws InterruptedException {
2 if (permits < 0) throw new IllegalArgumentException();
3 sync.acquireSharedInterruptibly(permits);
4 }

与此类似的还有:

acquireUninterruptibly()&acquireUninterruptibly(int)

tryAcquire()& tryAcquire(int)

tryAcquire(long,TimeUnit)& tryAcquire(int, long,TimeUnit)

release()& release(int)

aaarticlea/png;base64,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" alt="" />

1.2 使用示例:

 import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore; public class TIJ_semaphore {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
final Semaphore semp = new Semaphore(5); // 5 permits for (int index = 0; index < 20; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
try {
// if 1 permit avaliable, thread will get a permits and go; if no permit avaliable, thread will block until 1 avaliable
semp.acquire();
System.out.println("Accessing: " + NO);
Thread.sleep((long) (10000);
semp.release();
} catch (InterruptedException e) {
}
}
};
exec.execute(run);
}
exec.shutdown();
}

程序输出结果为:

 1 Accessing: 0
2 Accessing: 2
3 Accessing: 3
4 Accessing: 4
5 Accessing: 1
6 (等待10s)
7 Accessing: 5
8 Accessing: 6
9 Accessing: 14
10 Accessing: 8
11 Accessing: 7
12 (等待10s)
13 Accessing: 10
14 Accessing: 9
15 Accessing: 11
16 Accessing: 15
17 Accessing: 12
18 (等待10s)
19 Accessing: 13
20 Accessing: 16
21 Accessing: 17
22 Accessing: 19
23 Accessing: 18

2 CountDownLatch

2.1 实现

内部使用AQS实现

2.2 方法
await()

等待,无超时,可以被中断

 public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}

boolean await(long,timeUnit):

如果等待超时,则返回false; 如果时间为0或者为负,则立刻返回。

  public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}

countDown():

把Latch的计数减1,如果计数到达0,则释放所有正在等待的线程。

 public void countDown() {
sync.releaseShared(1);
}

2.3 使用:

绝大多数synchronizer在jdk中没有使用,原因很简单:这些synchronizer是抽象层次较高的,所以一般只有应用程序才会直接使用。

而在nts生产环境中,只有一处admin.rest.api.RestRequestSender使用了CountDownLatch:

    public Map<String, List<JSONObject>> doDelete(final String reqUri, final HttpHeaders _headers)
throws RestAPIException
{
setMethod(Method.DELETE);
setUriTemplate(reqUri);
headers = _headers;
return processBroadcast();
}

doDelete调用了processBraodcast:

   private Map<String, List<JSONObject>> processBroadcast() throws RestAPIException
{
...
final Map<String, SaaSServerContext> dServers = RestRequestSender.deployedServers;
if (!dServers.isEmpty())
{
final CountDownLatch doneSignal = new CountDownLatch(dServers.size());
...
for (final String key : dServers.keySet())
{
...
executor.submit(new RRSRunnable(doneSignal, context, results, key, totalRecordsCounter));
} try
{
if (!doneSignal.await(Configuration.NTS_MDM_API_BROADCAST_TIMEOUT.getInt(), TimeUnit.MINUTES)) // if timeout will retrun false
{
XLog.warning("MDM api broadcast timed out after " + Configuration.NTS_MDM_API_BROADCAST_TIMEOUT.getInt()
+ " minutes. Timeout is set via notes.ini key "
+ Configuration.NTS_MDM_API_BROADCAST_TIMEOUT.getNotesIniName());
}
}
catch (final InterruptedException ie)
{
throw new RestAPIException("Interrupted", ie);
} } return results; // if doneSingnal.await has been intrerrupted, will this line still execute?
}

RRSRunnable代码如下:

class RRSRunnable implements Runnable
{
private final CountDownLatch doneSignal;
... RRSRunnable(final CountDownLatch doneSignal, final SaaSServerContext context,
final Map<String, List<JSONObject>> results, final String serverKey,
final MaxRecordCounter recordCounter)
{
this.doneSignal = doneSignal;
...
} @Override
public void run()
{
...
try
{
processRequest(responses, context.getHostName(), client, context, recordCounter);
final long elapsedTime = System.currentTimeMillis() - startTime;
XLog.fine("Traveler API request completed. orgid=" + orgId + ";request=" + reqUri + ";pool=" + serverKey
+ ";time=" + elapsedTime + "ms");
}
catch (final RestAPIException rae)
{
exceptionServerKey = serverKey;
exception = rae;
}
finally
{
doneSignal.countDown();
}
}
}

2.4 更加一般的Latch:

CountDownLatch是一种特殊的Latch,jcip第八章用countdownLatch实现了一种valueLatch。

2.4.1 nts Latch简介:

在nts生产代码中也实现了一种Latch,Latch允许多个线程间的协作:在这种Latch中,有working thread和latching thread之分:

workingThread在做一些工作,latchingThread希望当这些工作完成的时候,锁存这些工作,然后得到workingThread的工作结果。workingThread和latchingThread共享一个Latch对象,workingThread会调用start方法,通知它正在开始针对特定Object的工作已经开始了。同时,latchingThread将调用latch方法,并传进它希望等待的Object。 当workingThread完成对某一Object(start方法传入的)的工作后,它将调用finish方法,传入该对象,以及工作的结果对象。当finish方法被调用后,调用latch方法的线程被唤醒,返回工作结果给latch方法的调用者。多个线程可以锁存同一个将要完成某些工作的object。一旦任意一个线程调用了finish方法,他们都将被唤醒并返回结果对象。如果调用latch方法时,针对latch对象的工作还没有开始,线程立刻返回,并不会block. 所以start(Object)应该首先被调用。

workingThread调用start(Object)方法,表明它开始工作。 同时,latchingThread调用latch(Object,long)方法,等待workingThread的执行完成。 workingThread执行finish(Object,Object)方法,表示工作完成,此时,latchingThread醒来。start(Object) finish(Object,Object) --> working thread 第二个参数为结果。 ?
latch(Object,long) --> latching thread

2.4.2 nts Latch 实现:

start:

    public boolean start(final Object obj)
{
final long timeStart = System.currentTimeMillis();
boolean rv = false;
Barrier b = null;
synchronized (this)
{
if (!latched.containsKey(obj))
{
b = new Barrier("Latch:" + name + "_Obj:" + obj, 1);
latched.put(obj, b); // latched is a synchronizedHashMap
rv = true;
}
}
XLog.exiting("name=" + name, "obj=" + obj, "barrier=" + b, "rv=" + rv, ("Elapsed time="
+ (System.currentTimeMillis() - timeStart) + "ms"));
return rv;
}

finish:

    public void finish(final Object obj, final Object result)
{
final long timeStart = System.currentTimeMillis();
final Barrier b;
synchronized (this)
{
b = latched.remove(obj);
if (null != b)
{
// there are waiters that need the result
b.result = result;
try
{
b.enter(0);
}
catch (final InterruptedException e)
{
// ignored
}
}
}
XLog.exiting("name=" + name, "obj=" + obj, "result=" + result, "barrier=" + b, ("Elapsed time="
+ (System.currentTimeMillis() - timeStart) + "ms"));
}

3 CyclicBarrier

CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它(一个线程)才执行; 而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行。

3.1 实现

使用Lock和Condition实现。不同于AQS。(Condition是基于AQS实现的)

CyclicBarrier包含下面的域:

     /** The lock for guarding barrier entry */
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
private final Condition trip = lock.newCondition();

3.1.1 构造函数

当在等待栅栏的线程个数到达预定义的个数时,barrier 发生trip, 但是因为没有预定义的动作,所以不执行任何动作。

1     public CyclicBarrier(int parties) {
2 this(parties, null);
3 }

当barrier发生trip时,会由最后一个进入该barrier的线程执行特定的动作:

1    public CyclicBarrier(int parties, Runnable barrierAction) {
2 if (parties <= 0) throw new IllegalArgumentException();
3 this.parties = parties;
4 this.count = parties;
5 this.barrierCommand = barrierAction;
6 }

CyclicBarrier方法

await():

 public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}

await(Long time, TimeUtil unit):

1     public int await(long timeout, TimeUnit unit)
2 throws InterruptedException,
3 BrokenBarrierException,
4 TimeoutException {
5 return dowait(true, unit.toNanos(timeout));
6 }

上述两种方法都调用了dowait方法:

  private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Generation g = generation;
...
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
} int index = --count;
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
} // loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
if (!timed)
/* The lock associated with this Condition is atomically
     released and the current thread becomes disabled for thread scheduling
     purposes */
trip.await();
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
} if (g.broken)
throw new BrokenBarrierException(); if (g != generation)
return index; if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}

breakBarrier:

     private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}

3.2 使用:

在jdk和traveler code中没有使用。这符合Effective Java 69中的描述。在实际使用中较少见到。

4 Synchronizere与wait()/wait(long)/wait(long,int)/notify()/notifyAll()的比较:

在effective java 69中提到,wait()/wait(long)/wait(long,int)/notify()/notifyAll()不易使用且容易出错。一般来讲应该优选更高级的concurrent container 或者 synchronizer。 其中synchronizer比较常用的是Semaphore和CountDownLatch,而CyclicBarrier和Exchanger 则使用的比较少。说从易用性上来讲,wait()/notify()/notifyAll()更象是汇编语言,并发容器和synchronizer更像是高级语言。 但我在nts代码中看到了很多wait/notify,而Semaphore和CountDownLatch则用的很少。

Lock/Condition()是使用AQS实现的,Lock/Condition() 组合可以用来替代Object.wait()/notify()。 而高级的synchronizer: CountDownLatch& Semaphore也是基于AQS实现的。所以理论上,可以替代wait/notify。 Semaphore和CountDownLatch也都包含了跟wait(long timeout)相对应的方法。

    考虑以下在下面的例子中,是否可以用Semaphore& CountDownLatch来代替wait/notify ?

  public Connection getConnection(final boolean highpriority) throws SQLException
{
final long sTime = System.currentTimeMillis();
Connection conn = null;
boolean createConnection = false;
boolean waitConnection = false; try
{
while (true)
{
createConnection = false;
waitConnection = false; synchronized (dbConnections)
{ final List<Connection> dbConnectionsToBeFreedTemp = new ArrayList<Connection>();
synchronized (dbConnectionsToBeFreed)
{
if (!dbConnectionsToBeFreed.isEmpty())
{
dbConnectionsToBeFreedTemp.addAll(dbConnectionsToBeFreed);
dbConnectionsToBeFreed.clear();
if (1 == dbConnectionsToBeFreedTemp.size())
{
// only one, so only notify one
dbConnectionsToBeFreed.notify(); // Semaphore.release()
}
else
{
dbConnectionsToBeFreed.notifyAll(); // CountDownLatch.await()
}
}
if (isThrottDown && connectionCount <= Tier.ONE.value * .20F)
{
isThrottDown = false;
dbConnectionsToBeFreed.notifyAll();
}
} if (!dbConnectionsToBeFreedTemp.isEmpty())
{
for (final Connection connToFree : dbConnectionsToBeFreedTemp)
{
if (!closeConnectionIfAgedOut(connToFree))
{
dbConnections.add(connToFree);
}
}
dbConnectionsToBeFreedTemp.clear();
} if (Configuration.NTS_DB_CONNECTION_THROTTLING.getBoolean())
{
getCurrentTier(); if ((!dbConnections.isEmpty() && !isThrottDown)
&& (highpriority || ((connectionCount - dbConnections.size()) < currentTier.value))) //Prevent non-high priority requests from grabbing freed high priority connections if connection is capped
{
conn = dbConnections.remove(0);
} if (null == conn)
{
// See if we should create a new connection or have to wait
// if none are in the stack, then see if we should make another
if ((connectionCount < currentTier.value || (highpriority && (connectionCount < maxConnectionCount)))
&& !isThrottDown)
{ createConnection = true;
connectionCount++;
}
else if (!isScheduled && conn == null && !highpriority && !createConnection
&& currentTier != Tier.THREE && !isThrottDown)
{
WallClock.getInstance().addAlarm(ALARM_NAME,
Configuration.NTS_DB_POOL_STEP_INTERVAL_TIMER.getInt(), alarmStepUpTier);
isScheduled = true;
waitConnection = true;
}
else if (conn == null && !createConnection && currentTier == Tier.THREE
&& connectionCount - dbConnections.size() >= Tier.THREE.value && !isScheduled)
{
WallClock.getInstance().addAlarm(ALARM_THROTTLE_DOWN,
Configuration.NTS_DB_POOL_STEP_INTERVAL_TIMER.getInt(), alarmThrottleDown);
isScheduled = true;
waitConnection = true;
}
else
{
// Connections are maxed out, so we have to wait
waitConnection = true;
}
}
}
else
{
if (!dbConnections.isEmpty()
&& (highpriority || ((connectionCount - dbConnections.size()) <= maxConnectionCount)))
{
conn = dbConnections.remove(0);
} if (null == conn)
{
// See if we should create a new connection or have to wait
// if none are in the stack, then see if we should make another
if ((connectionCount < maxConnectionCount) || highpriority)
{ createConnection = true;
connectionCount++;
}
else
{
// Connections are maxed out, so we have to wait
waitConnection = true;
}
}
}
} if (null != conn)
{
// we have a Connection, so we are done
break;
}
else if (createConnection)
{
if (!isDerby)
{
// update user and password from Configuration
connProps.put("user", Configuration.NTS_DBUSER.getString());
connProps.put("password", Configuration.NTS_DBPASSWORD.getString());
} try
{
conn = DriverManager.getConnection(url, connProps);
}
catch (final SQLException sqle)
{
connectionCount--; // count must be decremented since a connection was never created
DatabaseStatus.reportException(sqle);
throw sqle;
} if (conn != null)
{
DatabaseStatus.clearException();
if (peakConnections < connectionCount)
{
peakConnections = connectionCount;
Stats.setStat(Stats.DB_POOL_PEAK_CONNECTIONS_COUNT, peakConnections);
Stats.setStat(Stats.DB_POOL_PEAK_CONNECTIONS_TIME, new Date().toString());
}
allConnections.put(Integer.valueOf(conn.hashCode()), PersistentStore.createDeathTimeStamp()); break;
}
else if (Configuration.NTS_DB_CONNECTION_THROTTLING.getBoolean())
{
// Unexpected Database exceptions will result in connection == null.
// Instead of retrying the connection, throw a checked exception.
throw new DBConnectionsAllUsedException("There are no DB Connections available");
}
else
{
// don't break which will do the retry
}
}
else if (waitConnection)
{
try
{
Stats.inc(Stats.DB_THREADS_WAITING_FOR_CONNECTION);
synchronized (dbConnectionsToBeFreed)
{
dbConnectionsToBeFreed.wait(); // Semaphore.acquire() CountDownLatch.countdown()
}
}
finally
{
Stats.dec(Stats.DB_THREADS_WAITING_FOR_CONNECTION);
}
// don't break which will do the retry
}
else
{
// should never hit this case
break;
}
}
}
catch (final InterruptedException ie)
{
// expected
throw new SQLException("Exception waiting for DB connection.", ie);
}
finally
{ } return conn;
}

5 进一步问题:

5.1 CyclicBarrier方法,await(): 为什么要提供这两种方法来包裹wrapper dowait方法?

5.2 Semaphore和CountDownLatch互换

 final Semaphore sem = new Semaphore(0);
for (int i = 0; i < num_threads; ++ i)
{
Thread t = new Thread() {
public void run()
{
try
{
doStuff();
}
finally
{
sem.release();
}
}
};
t.start();
} sem.acquire(num_threads);
 

 

 final CountDownLatch latch = new CountDownLatch(num_threads);
for (int i = 0; i < num_threads; ++ i)
{
Thread t = new Thread() {
public void run()
{
try
{
doStuff();
}
finally
{
latch.countDown();
}
}
};
t.start();
} latch.await();
 

6 参考文献
 http://www.cnblogs.com/dolphin0520/p/3920397.html

----- 单例 -----

单例与static方法的区别: 一个是实例,可以传递,另外一个不可以。(好像也没什么用,传递单例)。

http://stackoverflow.com/questions/519520/difference-between-static-class-and-singleton-pattern#

 

最新文章

  1. Redis初识
  2. EMF学习,为了实现可扩展可自定义的模型验证 - 各种实现方法学习
  3. C#之发送邮件汇总
  4. 导出websphere内存镜像
  5. Linux内核中的fastcall和asmlinkage宏
  6. uva 11143
  7. USB状态错误原因
  8. HADOOP集群监控工具AMBARI
  9. 检测iOS系统的定位服务
  10. 【转】生产环境MySQL Server核心参数的配置
  11. 跟我一起学extjs5(19--模块记录的拖放删除、拖放复制新增)
  12. qt example
  13. Win32 Windows编程 十二
  14. fcntl()
  15. abap alv multiple header using write
  16. XLua----热更新
  17. Android开发过程中的坑及解决方法收录(一)
  18. Keras实现卷积神经网络
  19. MyChatRoom——C#自制聊天室
  20. [转]Oracle存储过程总结

热门文章

  1. 【mysql】mysql 配置
  2. OpenCV之cvAddWeighted直接C语言实现版addWeighted,应对上下平滑融合拼接
  3. fstab 解析
  4. mysql用户权限操作
  5. 捷宇高拍仪XY530 网页集成总结
  6. 详细步骤教你安装yii高级应用程序和配置composer环境
  7. 微信小程序(底部导航的实现)
  8. JavaScript: apply , call 方法
  9. Atom打造轻量化C/C++ IDE
  10. Java 使用正则表达式取出图片地址以及跳转的链接地址,来判断死链(一)