技术开发 频道

关于java.util.concurrent不知的事(二)

  2. CountDownLatch

  如果 Semaphore 是允许一次进入一个(这可能会勾起一些流行夜总会的保安的记忆)线程的并发性类,那么 CountDownLatch 就像是赛马场的起跑门栅。此类持有所有空闲线程,直到满足特定条件,这时它将会一次释放所有这些线程。

  清单 2. CountDownLatch:让我们去赛马吧!

import java.util.*;
import java.util.concurrent.
*;

class Race
{
    
private Random rand = new Random();
    
    
private int distance = rand.nextInt(250);
    
private CountDownLatch start;
    
private CountDownLatch finish;
    
    
private List<String> horses = new ArrayList<String>();
    
    
public Race(String... names)
    {
        this.horses.addAll(Arrays.asList(names));
    }
    
    
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
                    {
                        System.out.println(h
+
                            
" stepping up to the gate...");
                        start.await();
                        
                        
int traveled = 0;
                        
while (traveled < distance)
                        {
                            
// In a 0-2 second period of time....
                            Thread.sleep(rand.nextInt(
3) * 1000);
                            
                            
// ... a horse travels 0-14 lengths
                            traveled
+= rand.nextInt(15);
                            System.out.println(h
+
                                
" advanced to " + traveled + "!");
                        }
                        finish.countDown();
                        System.out.println(h
+
                            
" crossed the finish!");
                        places.add(h);
                    }
                    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(
"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.");
    }
}

public class CDLApp
{
    
public static void main(String[] args)
        throws InterruptedException, java.io.IOException
    {
        System.out.println(
"Prepping...");
        
        Race r
= new Race(
            
"Beverly Takes a Bath",
            
"RockerHorse",
            
"Phineas",
            
"Ferb",
            
"Tin Cup",
            
"I'm Faster Than a Monkey",
            
"Glue Factory Reject"
            );
        
        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();
    }
}

  注意,在 清单 2 中,CountDownLatch 有两个用途:首先,它同时释放所有线程,模拟马赛的起点,但随后会设置一个门闩模拟马赛的终点。这样,“主” 线程就可以输出结果。 为了让马赛有更多的输出注释,可以在赛场的 “转弯处” 和 “半程” 点,比如赛马跨过跑道的四分之一、二分之一和四分之三线时,添加 CountDownLatch。

0
相关文章