刚学到这招,记录一下。
以前只知道闭锁就用来阻塞住主线程,然后等其他线程运行完,计数器到0的时候,放开闭锁,没想到还能这么玩儿。
这里还正好用来测试下单例在多线程下的问题,可以很明显的看到2个线程同时并发获取单例的时候,就会很大概率得到的不是一个对象了,这时候用同步方法、枚举、静态内部类或DCL就能解决这个问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;
class CountDownLatchUtil { private CountDownLatch start; private CountDownLatch end; private int count;
public CountDownLatchUtil() { this(1); }
public CountDownLatchUtil(int count) { start = new CountDownLatch(1); end = new CountDownLatch(count); this.count = count; }
public void latch(TaskFunction taskFunction) { ExecutorService pool = Executors.newFixedThreadPool(count); for (int i = 1; i <= count; ++i) { Runnable task = new Runnable() { @Override public void run() { try { start.await(); taskFunction.task(); } catch (InterruptedException e) { e.printStackTrace(); } finally { end.countDown(); } } }; pool.submit(task); } start.countDown(); try { end.await(); } catch (InterruptedException e) { e.printStackTrace(); } pool.shutdown(); }
@FunctionalInterface public static interface TaskFunction { void task(); } }
class Obj { private static Obj obj;
private Obj() { };
public static Obj getInstance() { if (obj == null) { obj = new Obj(); } return obj; } }
public class Main {
public static void main(String[] args) { CountDownLatchUtil latchUtil = new CountDownLatchUtil(2); long time = System.currentTimeMillis(); latchUtil.latch(() -> { System.out.println(Obj.getInstance()); }); System.out.println("运行耗时:" + (System.currentTimeMillis() - time) + "ms"); } }
|
输出:
Obj@6299d4f3
Obj@7f5b7c1b
运行耗时:47ms