参考:http://www.ibm.com/developerworks/cn/java/j-5things5.html
【关于 java.util.concurrent 您不知道的 5 件事,第 2 部分】
1,Semaphore
适用于:限制未处理的特定资源请求(线程/操作)数量。
public class SemApp {
public static void main(String[] args) {
Runnable limitedCall = new Runnable() {
final Random rand = new Random();
final Semaphore available = new Semaphore(3);
int count = 0;
public void run() {
int time = rand.nextInt(15);
int num = count++;
try {
available.acquire();
System.out.println("Executing " +
"long-running action for " +
time + " seconds... #" + num);
Thread.sleep(time * 1000);
System.out.println("Done with #" +
num + "!");
available.release();
} catch (InterruptedException intEx) {
intEx.printStackTrace();
}
}
};
for (int i=0; i<10; i++)
new Thread(limitedCall).start();
}
}
程序中实现了,限制了同时打开的任务数是三个。
结果 写道
Executing long-running action for 9 seconds... #0
Executing long-running action for 7 seconds... #2
Executing long-running action for 0 seconds... #1
Done with #1!
Executing long-running action for 1 seconds... #3
Done with #3!
Executing long-running action for 6 seconds... #4
Done with #2!
Executing long-running action for 5 seconds... #5
Done with #4!
Executing long-running action for 6 seconds... #6
Done with #0!
Executing long-running action for 12 seconds... #7
Done with #5!
Executing long-running action for 1 seconds... #8
Done with #8!
Executing long-running action for 12 seconds... #9
Done with #6!
Done with #7!
Done with #9!
对于特定资源和线程访问数的限定Semaphore是个不错的选择。这里使用了Semaphore一次使用和释放一个通行证,Semaphore还可以一次使用和释放多个通行证。
2,CountDownLatch
public class CDLApp {
public static void main(String[] args)
throws InterruptedException, java.io.IOException {
System.out.println("Prepping...");
Race r = new Race(
"horse 1", "horse 2", "horse 3", "horse 4",
"horse 5", "horse 6", "horse 7", "horse 8"
);
System.out.println("It's a race of " + r.getDistance() + " lengths");
System.out.println("Press Enter to run the race....");
System.in.read();
r.run();
}
}
class Race {
private Random rand = new Random();
private int distance = rand.nextInt(250);
private List<String> horses = new ArrayList<String>();
public Race(String... names) {
this.horses.addAll(Arrays.asList(names));
}
public int getDistance() {return distance;}
public void run() throws InterruptedException {
System.out.println("And the horses are stepping up to the gate...");
final CountDownLatch start = new CountDownLatch(1);
final CountDownLatch finish = new CountDownLatch(horses.size());
final List<String> places =
Collections.synchronizedList(new ArrayList<String>());
for (final String h : horses) {
new Thread(new Runnable() {
public void run() {
try {
start.await();//等待赛马开始
System.out.println(h +
" stepping up to the gate...");
int traveled = 0;
while (traveled < distance) {
//前进一次 暂停 0-2 秒
Thread.sleep(rand.nextInt(3) * 1000);
//前进 0-14 米
traveled += rand.nextInt(15);
System.out.println(h +
" advanced to " + traveled + "!");
}
System.out.println(h +
" crossed the finish!");
places.add(h);
finish.countDown();//一个马到达终点就 减去一, 倒数完成比赛结束
}
catch (InterruptedException intEx) {
System.out.println("ABORTING RACE!!!");
intEx.printStackTrace();
}
}
}).start();
}
System.out.println("And... they're off!");
start.countDown();//开始赛马
finish.await();//等待所有的马跑完
System.out.println("============================================");
System.out.println("And we have our winners!");
System.out.println("<"+places.get(0)+">" + " took the gold...");
System.out.println("<"+places.get(1)+">" + " got the silver...");
System.out.println("and " + "<"+places.get(2)+">" + " took home the bronze.");
System.out.println("============================================");
}
}
上面的程序利用CountDownLatch 描述一个赛马的过程,首先让所有马在门闩那里(start.countDown();//开始赛马)等待开始,每匹马冲过终点后(finish.countDown),finish.await()等待所有的马冲过终点后,发奖牌。
3,ScheduledExecutorService
public class Ping {
public static void main(String[] args) {
ScheduledExecutorService ses =
Executors.newScheduledThreadPool(1);
Runnable pinger = new Runnable() {
public void run() {
System.out.println("PING!");
}
};
ses.scheduleAtFixedRate(pinger, 1, 2, TimeUnit.SECONDS);
}
}
模拟心脏每隔2秒钟跳动一次。顺便说一下,如果用户希望取消心跳,scheduleAtFixedRate
调用将返回一个 ScheduledFuture
实例,它不仅封装了结果(如果有),还拥有一个 cancel
方法来关闭计划的操作。