CountDownLatch的2个用途:
1. 所有线程都到达相同的起跑线后,再一起开始跑(并非同时开始,而是队列中一个唤醒另一个)【此情况需到达起跑线后再调用await()等待其他线程】
2. 所有线程都到达终点(执行完)后,再一起庆祝 (并非同时开始,而是队列中一个唤醒另一个)【此情况需到达起终点后再调用await()等待其他线程】
package com.study.concurrent_utils; import java.util.concurrent.CountDownLatch; public class Test_CountDownLatch { /* * 没隔1s开启一个线程,共开启6个线程 * 若希望6个线程 同时 执行某一操作 * 可以用CountDownLatch实现 */ public static void test01() throws InterruptedException { CountDownLatch ctl = new CountDownLatch(6); for (int i = 0; i < 6; i++) { new Thread() { @Override public void run() { ctl.countDown(); try { ctl.await(); // 6个线程都启动执行到此处时,打印如下 System.out.println("here I am..."); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); Thread.sleep(1000L); } } /* * 开启6个线程,6个线程都执行完后,才执行某个操作 * 可以用CountDownLatch来实现 */ public static void test02() throws InterruptedException { JamesCountDownLatch ctl = new JamesCountDownLatch(6); for (int i = 0; i < 6; i++) { new Thread() { @Override public void run() { System.out.println("after print..."); ctl.countDown(); } }.start(); Thread.sleep(1000L); } ctl.await(); // 6条线程都执行完后同时打印这句话 System.out.println("main thread do something ..."); } public static void main(String args[]) throws InterruptedException { test02(); } }
手写CountDownLatch(基于AQS)
countDown()方法:释放共享锁,首先会尝试释放共享锁(其实际是做CAS操作将state减1,如果state减到了0,返回true),如果返回true,说明读锁已释放完,则将等待队列头部线程唤醒。
await()方法:获取共享锁,首先会尝试获取共享锁(其实际操作,获取并判断state值:return getState()==0 ? 1: -1;),若state不是0,即所有线程还没到齐,集体活动还不能开始,此时将其加入等待队列,并且开始自旋,不断判断自己是不是队列头部,即下一个开始跑的是不是自己,是的话就再次尝试获取共享锁,若失败就将自己挂起,若成功即从等待队列移除,并唤醒下一个要获取共享锁的线程。
package com.study.concurrent_utils; import java.util.concurrent.locks.AbstractQueuedSynchronizer; public class JamesCountDownLatch { private Sync sync; public JamesCountDownLatch(int count) { sync = new Sync(count); } public void countDown() { sync.releaseShared(1); } public void await() { sync.acquireShared(1); } class Sync extends AbstractQueuedSynchronizer { public Sync(int count) { setState(count); } @Override protected int tryAcquireShared(int arg) { // 只有当state变为0时,加锁成功 return getState() == 0 ? 1 : -1; } /* * countdown的方法 */ @Override protected boolean tryReleaseShared(int arg) { for (;;) { int c = getState(); if (c == 0) return false; int nextc = c - arg; // 用CAS操作,讲count减一 if (compareAndSetState(c, nextc)) { // 当state=0时,释放锁成功,返回true return nextc == 0; } } } } }
手写Semaphore(基于AQS)
package com.study.concurrent_utils; import java.util.concurrent.locks.AbstractQueuedSynchronizer; public class JamesSemaphore { private Sync sync; public JamesSemaphore(int state) { sync = new Sync(state); } public void acquire() { sync.acquireShared(1); } public void release() { sync.releaseShared(1); } class Sync extends AbstractQueuedSynchronizer { int state; public Sync(int state) { this.state = state; } @Override protected int tryAcquireShared(int arg) { for (;;) { int available = getState(); int remaining = available - arg; if (remaining < 0 || compareAndSetState(available, remaining)) return remaining; } } @Override protected boolean tryReleaseShared(int arg) { for (;;) { int current = getState(); int next = current + arg; if (next < current) // overflow throw new Error("Maximum permit count exceeded"); if (compareAndSetState(current, next)) return true; } } } }
package com.study.concurrent_utils; import java.util.concurrent.CyclicBarrier; public class TestCyclicBarrier { public static void main(String[] args) throws InterruptedException { CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() { @Override public void run() { System.out.println(">>>>3个已满,走起<<<"); } }); for (int i = 0; i < 30; i++) { new Thread(new Runnable() { @Override public void run() { try { cyclicBarrier.await(); System.out.println(Thread.currentThread() + ":start..."); } catch (Exception e) { e.printStackTrace(); } } }).start(); Thread.sleep(1000L); } } }
>>>>3个已满,走起<<< Thread[Thread-2,5,main]:start... Thread[Thread-0,5,main]:start... Thread[Thread-1,5,main]:start... >>>>3个已满,走起<<< Thread[Thread-5,5,main]:start... Thread[Thread-3,5,main]:start... Thread[Thread-4,5,main]:start... >>>>3个已满,走起<<< Thread[Thread-8,5,main]:start... Thread[Thread-6,5,main]:start... Thread[Thread-7,5,main]:start...
手写CyclicBarrier(基于ReentrantLock)
ReentrantLock的Condition就是一个等待队列,ReentrantLock是一个可重入锁
package com.study.concurrent_utils; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class JamesCyclicBarrier { private final ReentrantLock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); // 记录当前这个批次有多少个 private int count = 0; // 记录批次的大小 private final int parties; // 分代 private Object generation = new Object(); public JamesCyclicBarrier(int parties) { if (parties <= 0) throw new IllegalArgumentException(); this.parties = parties; } // 进入下一个分代 public void nextGeneration() { condition.signalAll(); count = 0; generation = new Object(); } public void await() { // 实现排队,需要将线程放到等待队列 // 还需要将线程挂起 // final ReentrantLock lock = this.lock; lock.lock(); try { // 记录当前的generation,相当于记录当前批次的id final Object g = generation; int index = ++count; // 批次已经达到parties, if (index == parties) { // 进入下一个批次 nextGeneration(); return; } // 若未达到批次,就进入等待 for (;;) { try { condition.await(); } catch (InterruptedException e) { } if (g != generation) { return; } } } finally { lock.unlock(); } } }
Future/Runnable
package com.study.futuretask; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.concurrent.locks.LockSupport; public class Demo3_CallableTest { public static void main(String args[]) throws InterruptedException, ExecutionException { CallTask cTask = new CallTask(); JamesFutureTaskfTask = new JamesFutureTask (cTask); // 执行第一次 Thread th = new Thread(fTask); th.start(); System.out.println("begain to get..."); String result = fTask.get(); System.out.println(result); // 执行第二次,失败 Thread th1 = new Thread(fTask); th1.start(); } } class CallTask implements Callable { @Override public String call() throws Exception { LockSupport.parkNanos(1000 * 1000 * 1000 * 5L); System.out.println("done..."); return "James"; } }
手写FutureTask
package com.study.futuretask; import java.util.concurrent.Callable; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.LockSupport; public class JamesFutureTaskimplements Runnable { // future只能执行一次 private volatile int state = NEW; private static final int NEW = 0; private static final int RUNNING = 1; private static final int FINISED = 2; public JamesFutureTask(Callable task) { this.callable = task; } // 程序执行的结果 private T result; // 要自行的task Callable callable; // 获取结果的线层等待队列 LinkedBlockingQueue waiters = new LinkedBlockingQueue<>(100); // 执行当前FutureTask的线程,用CAS进行争抢 AtomicReference runner = new AtomicReference<>(); @Override public void run() { // 判断当前对象的状态,如果是New就执行,如果 if (state != NEW || !runner.compareAndSet(null, Thread.currentThread())) return; state = RUNNING; try { result = callable.call(); } catch (Exception e) { e.printStackTrace(); } finally { state = FINISED; } // 方法执行完,唤醒所有线程 while (true) { Thread waiter = waiters.poll(); if (waiter == null) break; LockSupport.unpark(waiter); } } public T get() { if (state != FINISED) { waiters.offer(Thread.currentThread()); } while (state != FINISED) { LockSupport.park(); } return result; } }