Last active
April 11, 2018 05:28
-
-
Save BadUncleX/9f0361251a3f1ab54f2cbdbd3a4e5eb3 to your computer and use it in GitHub Desktop.
CountDownLatch 同步计数器 运动员跑步比赛
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CountDownLatch 同步计数器 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package countdownlatch_usage; | |
// | |
// from here: https://stackoverflow.com/questions/17827022/how-is-countdownlatch-used-in-java-multithreading | |
// | |
import java.util.concurrent.CountDownLatch; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
class Processor implements Runnable { | |
private CountDownLatch latch; | |
public Processor(CountDownLatch latch) { | |
this.latch = latch; | |
} | |
public void run() { | |
System.out.println("Started."); | |
try { | |
Thread.sleep(3000); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
latch.countDown(); | |
} | |
} | |
class App { | |
public static void main(String[] args) { | |
CountDownLatch latch = new CountDownLatch(3); // coundown from 3 to 0 | |
ExecutorService executor = Executors.newFixedThreadPool(3); // 3 Threads in pool | |
for(int i=0; i < 3; i++) { | |
executor.submit(new Processor(latch)); // ref to latch. each time call new Processes latch will count down by 1 | |
} | |
try { | |
latch.await(); // wait until latch counted down to 0 | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
System.out.println("Completed."); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package countdownlatch_usage;// | |
// from here: https://blog.csdn.net/u013136708/article/details/49444459 | |
// 比如一个跑步比赛,有五个选手参加,有两点需要注意,第一我们必须确保这5个 | |
// 选手都准备就绪了,才能宣布比赛开始,第二只有当5个选手都完成比赛了才能宣布比赛结束。 | |
/** | |
CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞程序继续执行 | |
CountDownLatch如其所写,是一个倒计数的锁存器,当计数减至0时触发特定的事件。利用这种特性,可以让主线程等待子线程的结束。下面以一个模拟运动员比赛的例子加以说明。 | |
*/ | |
import java.util.concurrent.CountDownLatch; | |
import java.util.concurrent.Executor; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
public class CountDownLatchDemo { | |
private static final int PLAYER_AMOUNT = 5; | |
public CountDownLatchDemo() { | |
// TODO Auto-generated constructor stub | |
} | |
/** | |
* @param args | |
*/ | |
public static void main(String[] args) { | |
// TODO Auto-generated method stub | |
//begin为了确保每个运动员都准备就绪了才能开始比赛,所以每个运动员都会持有一个begin,并且调用begin.await()方法进入等待。 | |
CountDownLatch begin = new CountDownLatch(1); | |
//对于整个比赛,所有运动员结束后才算结束。主线程会持有end,确保所有的运动员都到终点才能宣布比赛结束。同时每个运动员到达终点的时候都会调用,end.countdown()方法。 | |
CountDownLatch end = new CountDownLatch(PLAYER_AMOUNT); | |
Player[] plays = new Player[PLAYER_AMOUNT]; | |
for(int i=0;i<PLAYER_AMOUNT;i++) | |
plays[i] = new Player(i+1,begin,end); | |
//设置特定的线程池,大小为5 | |
ExecutorService exe = Executors.newFixedThreadPool(PLAYER_AMOUNT); | |
for(Player p:plays) | |
//分配线程,每个运动员都准备就绪,但是没有开始赛跑,因为他们持有的begin都调用了begin.await() | |
exe.execute(p); | |
System.out.println("Race begins!");//宣布比赛开始 | |
//所有运动员开始赛跑,begin的参数减少1,变为0,持有begin.await的线程开始运行。 | |
begin.countDown(); | |
try{ | |
//等待所有的运动员都到达终点,比赛结束。 | |
end.await(); | |
}catch (InterruptedException e) { | |
// TODO: handle exception | |
e.printStackTrace(); | |
}finally{ | |
System.out.println("Race ends!");//宣布比赛结束 | |
} | |
exe.shutdown(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; | |
;; from Dennis: http://www.blogjava.net/killme2008/archive/2010/08/archive/2010/07/17/326389.html | |
;; 使用atom实现一个计数器,和使用java.util.concurrent.AtomicInteger做计数器, | |
;; 做一个性能比较,各启动100个线程,每个线程执行100万次原子递增,计算各自的耗时 | |
(ns countdownlatch_usage) | |
(import 'java.util.concurrent.atomic.AtomicInteger) | |
(import 'java.util.concurrent.CountDownLatch) | |
(def a (AtomicInteger. 0)) | |
(def b (atom 0)) | |
;;为了性能,给java加入type hint | |
(defn java-inc [#^AtomicInteger counter] (.incrementAndGet counter)) | |
(defn countdown-latch [#^CountDownLatch latch] (.countDown latch)) | |
;;单线程执行缓存次数 | |
(def max_count 1000000) | |
;;线程数 | |
(def thread_count 100) | |
;; 让多个线程一起开始 | |
;; 这里直接用的Thread新起一个进程, 而不是Future | |
(defn benchmark [fun] | |
(let [ latch (CountDownLatch. thread_count) ;;关卡锁 | |
start (System/currentTimeMillis) ] ;;启动时间 | |
(dotimes [_ thread_count] (.start (Thread. #(do (dotimes [_ max_count] (fun)) (countdown-latch latch))))) | |
(.await latch);; 阻塞等待全部结束. | |
(- (System/currentTimeMillis) start))) | |
(println "atom:" (benchmark #(swap! b inc))) | |
(println "AtomicInteger:" (benchmark #(java-inc a))) | |
(println (.get a)) | |
(println @b) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment