Concurrency tool classes
This series of articles mainly on Java
concurrency related content, including synchronization, lock, semaphore, blocking queue, thread pool, etc., the overall mind map as follows:
Series of articles list:
- Java Concurrency Foundation-concurrency model, base interface, and thread
- Java Concurrency Basics-synchronization and locks
In this paper, the main examples are explained CountDownLatch
, Semaphore
blocking queues and thread pool and other content.
Countdownlatch Basic concepts and uses
CountDownLatch
The primary is to allow one or more threads to wait until the other thread executes the operation.
Its source code implementation is mainly used AQS
, specific reference to the Java
concurrent basis-synchronization and lock.
The constructor method CountDownLatch
( int
count
) is used to initialize the counter, which is actually count
state
the initial value of the set (eventually the set value). After the value is set, it cannot be reset, and it can be used instead when the thread must repeatedly count down in this way CyclicBarrier
.
countDown()
method is used to reduce the value of the counter, minus each time 1
.
getCount()
method is used to return the value of the current counter.
The flowchart is simplified as follows
Run the sample
In the Synchronizeddemo
code, we use the join method of Thread
to wait for a spender
and After the earner
thread finishes running, get the value of the account balance balance
, where we use the Countdownlatch
counter to block the main thread for a set After Spender
and a set of earner
threads are complete, let the main thread get the value of the account balance, as follows:
Package Com.molyeo.java.concurrent;import Java.util.concurrent.countdownlatch;import Java.util.concurrent.executorservice;import java.util.concurrent.executors;/** * Created by Zhangkh on 2018/7/17. */public class Countdownlatchdemo {public static void main (string[] args) throws Interruptedexception {System. Out.println ("Main thread start"); Account Account = new account (); Account.setbalance (100000); Countdownlatch latch = new Countdownlatch (20); System.out.println ("Main latch init=" +latch.getcount ()); Executorservice Executorservice = Executors.newfixedthreadpool (10); for (int i = 0; i < i++) {Spenderwithcountdownlatch spender = new Spenderwithcountdownlatch (account, LA TCH); Executorservice.submit (spender); } for (int i = 0; i < i++) {Earnerwithcountdownlatch earner = new Earnerwithcountdownlatch (accou NT, latch); Executorservice.submit (earner); } System.out.println ("Main thread block"); Latch.await (); System.out.println ("Main latch=" +latch.getcount ()); System.out.println ("Main thread continue to do"); System.out.println ("balance=" +account.getbalance ()); Executorservice.shutdown (); }}
The first initialized CountDownLatch
value is 20
, and then the distribution creates a set of Spender
threads (each group 10
) and a set of Earner
threads (each group 10
), and account
latch
passes them to those threads.
SpenderWithCountDownLatch
The code below, the main time the operation is 30
to reduce the account balance, each decrease 1000
. Called when the run latch
countDown()
is complete, reducing the value of the counter.
public class SpenderWithCountDownLatch implements Runnable { private final Account account; private final CountDownLatch latch; public SpenderWithCountDownLatch(Account account, CountDownLatch latch) { this.account = account; this.latch = latch; } @Override public void run() { for (int i = 0; i < 30; i++) { account.subtractAmount(1000); } latch.countDown(); System.out.println("Spender run ......"); }}
EarnerWithCountDownLatch
The code below, the runtime is mainly the 30
second increase in the account balance, each increase 1000
. Called when the run latch
countDown()
is complete, reducing the value of the counter.
public class EarnerWithCountDownLatch implements Runnable { private final Account account; private final CountDownLatch latch; public EarnerWithCountDownLatch(Account account, CountDownLatch latch) { this.account = account; this.latch = latch; } @Override public void run() { for (int i = 0; i < 30; i++) { account.addAmount(1000); } latch.countDown(); System.out.println("Earner run ...." ); }}
Account
The code below needs to take advantage of synchronization blocks or Lock
guarantees addAmount
and subtractAmount
methods for thread safety
public class Account { private double balance; public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public void addAmount(double amount) { synchronized (Account.class) { balance = balance + amount; } } public void subtractAmount(double amount) { synchronized (Account.class) { balance = balance - amount; } }}
The entire program output is as follows:
main thread startmain latch init=20main thread blockSpender run ......Spender run ......Spender run ......Earner run ....Earner run ....Earner run ....Earner run ....Earner run ....Earner run ....Spender run ......Earner run ....Earner run ....Spender run ......Earner run ....Earner run ....Spender run ......Spender run ......Spender run ......Spender run ......Spender run ......main latch=0main thread continue to dobalance=100000.0
Satisfies the expected result 100000
, while the main thread blocks until latch
the value is 0
.
Cyclicbarrier basic concepts and main methods
CyclicBarrier
Allows a group of threads to wait for each other until all threads reach the public barrier point ( common
barrier
point
). And CountDownLatch
the difference is that it CyclicBarrier
can be reset and reused after releasing the waiting thread.
Construction method
public CyclicBarrier(int parties, Runnable barrierAction)
Which parties
represents the number of threads, that is, the number of participants
barrierAction
Represents the barrier
execution of the specified action at startup, which is performed by the last incoming barrier
thread
Await ()
Participants are blocked waiting until all the participants arrivebarrier
The flowchart is simplified as follows
Using the example
Let's take a look at the following example, where the main thread, Spender
thread, and Earner
thread share one barrier
, where the barrier
initial value is 3
that three threads arrive barrier
after BarrierAction
the defined action is executed.
Package Com.molyeo.java.concurrent;import Java.util.concurrent.brokenbarrierexception;import Java.util.concurrent.cyclicbarrier;import Java.util.concurrent.executorservice;import java.util.concurrent.executors;/** * Created by Zhangkh on 2018/9/5. */public class Cyclicbarrierdemo {public static void main (string[] args) {account account=new account (); Account.setbalance (100000); Cyclicbarrier barrier = new Cyclicbarrier (3, New barrieraction ()); Executorservice Executorservice = Executors.newfixedthreadpool (10); Spenderwithcyclicbarrier spender = new Spenderwithcyclicbarrier (account, barrier); Executorservice.submit (spender); Earnerwithcyclicbarrier earner = new Earnerwithcyclicbarrier (account, barrier); Executorservice.submit (earner); try{System.out.println (String.Format ("%20s waiting at Barrier", Thread.CurrentThread (). GetName ())); Barrier.await (); }catch (Interruptedexception e) { E.printstacktrace (); }catch (brokenbarrierexception e) {e.printstacktrace (); } System.out.println ("Balance=" +account.getbalance ()); System.out.println (String.Format ("%20s Done", Thread.CurrentThread (). GetName ())); }}class Barrieraction implements runnable{public void run () {System.out.println (String.Format ("%20s executed", Thread.CurrentThread (). GetName ()); }}class Spenderwithcyclicbarrier implements Runnable {private final account account; Private final cyclicbarrier barrier; Public Spenderwithcyclicbarrier (account account, Cyclicbarrier barrier) {this.account = account; This.barrier = barrier; } @Override public void Run () {for (int i = 0; i <; i++) {account.subtractamount (1000); } try{System.out.println (String.Format ("%20s waiting at Barrier", Thread.CurrentThread (). GetName () )); Barrier.await (); }catch (interruptedexceptione) {e.printstacktrace (); }catch (brokenbarrierexception e) {e.printstacktrace (); } System.out.println (String.Format ("%20s Done", Thread.CurrentThread (). GetName ())); }}class Earnerwithcyclicbarrier implements Runnable {private final account account; Private final cyclicbarrier barrier; Public Earnerwithcyclicbarrier (account account, Cyclicbarrier barrier) {this.account = account; This.barrier = barrier; } @Override public void Run () {for (int i = 0; i <; i++) {account.addamount (1000); } try{System.out.println (String.Format ("%20s waiting at Barrier", Thread.CurrentThread (). GetName ())); Barrier.await (); }catch (interruptedexception e) {e.printstacktrace (); }catch (brokenbarrierexception e) {e.printstacktrace (); } System.out.println (String.Format ("%20s Done", Thread.CurrentThread (). GetName ())); }}class ACcount {private double balance; Public double GetBalance () {return balance; } public void Setbalance (double balance) {this.balance = balance; } public void Addamount (double amount) {synchronized (account.class) {balance = balance + amount; }} public void Subtractamount (double amount) {synchronized (account.class) {balance = Bal Ance-amount; } }}
The program output is as follows:
pool-1-thread-2 waiting at barrier main waiting at barrier pool-1-thread-1 waiting at barrier pool-1-thread-1 executed pool-1-thread-1 done pool-1-thread-2 done balance=100000.0 main done
We can see-- pool
1
thread
2
and after the main
thread executes the operation on the balance of the account, it arrives at the blocking wait,---the barrier
pool
1
thread
1
thread finally arrives, then by pool
- 1
- thread
- 1
The thread executes the predefined action, that is executed
, after the output, the three threads continue to execute the output of the other information.
Notice here that the output may be inconsistent, but the thread names on the third and fourth lines are either, or--or--- main
pool
1
thread
1
pool
1
thread
2
. There is no case where two thread names are different. This shows that the barrier
predefined action after arrival is performed by the last thread that arrives.
This article references
Java 7 Concurrency Cookbook
Concurrency-modle-seven-week
Java-concurrency
Java-util-concurrent
Java SE 8 Apidoc
About the author
Love programming, love studying, love sharing, love life
Focus on distributed, high concurrency, data mining
If you want to donate, please scan the code