CountDownLatch
The CountDownLatch class, located under the java.util.Concurrent package, enables count-like functionality. For example, if task A is waiting for the other four tasks to complete, CountDownLatch can be used to implement this feature.
The CountDownLatch class provides only one constructor: public CountDownLatch(int count) {}; The three most important methods in the CountDownLatch class are:
- public void await() throws InterruptedException { }; // The thread calling the await() method is suspended and waits until count is 0 before continuing
- public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; // Similar to await(), except to wait a certain amount of time before count has changed to 0
- public void countDown() { }; // Subtract count by 1
final CountDownLatch latch = new CountDownLatch(2);
new Thread(){
public void run(a) {
try {
System.out.println(Child thread+Thread.currentThread().getName()+"In process");
Thread.sleep(3000);
System.out.println(Child thread+Thread.currentThread().getName()+"Executed");
latch.countDown();
} catch(InterruptedException e) { e.printStackTrace(); }}; }.start();new Thread(){
public void run(a) {
try {
System.out.println(Child thread+Thread.currentThread().getName()+"In process");
Thread.sleep(5000);
System.out.println(Child thread+Thread.currentThread().getName()+"Executed");
latch.countDown();
} catch(InterruptedException e) { e.printStackTrace(); }}; }.start();try {
System.out.println("Wait for 2 child threads to complete...");
latch.await();
System.out.println("2 child threads have completed execution");
System.out.println("Continue executing the main thread");
} catch (InterruptedException e) {
e.printStackTrace();
}
Copy the code
Output result:
Thread the Thread -0The executing Thread Thread-1Waiting in execution2The child thread completes... Thread the Thread -0Thread-1completed2The child thread completes and continues to execute the main threadCopy the code
CyclicBarrier
Literally loopback fence, which allows a group of threads to wait for a certain state before all execute simultaneously. Cyclicbarriers are called loops because they can be reused once all waiting threads have been released. We’ll call this state a barrier for now, and the thread is in a barrier after calling the await() method.
The CyclicBarrier class is located under the java.util.concurrent package and CyclicBarrier provides two constructors:
public CyclicBarrier(int parties, Runnable barrierAction) {}public CyclicBarrier(int parties) {}Copy the code
The parties parameter specifies how many threads or tasks to wait until the barrier state is reached. The barrierAction argument is what will be executed when these threads all reach the Barrier state.
Then the most important method in CyclicBarrier is the await method, which has two overloaded versions:
public int await(a) throws InterruptedException, BrokenBarrierException {};public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException {};Copy the code
The first version is commonly used to suspend the current thread until all threads reach the barrier state and then execute subsequent tasks simultaneously.
The second version makes these threads wait for a certain amount of time, and if there are any threads that haven’t reached the Barrier state, the threads that have reached the barrier do the subsequent tasks.
Here are a few examples:
You can use a CyclicBarrier if you have several threads that need to write data, and they can’t continue until all of them have done so. Cyclicbarriers can also be reused, as shown in this example:
public class Test {
public static void main(String[] args) {
int N = 4;
CyclicBarrier barrier = new CyclicBarrier(N);
for(int i=0; i<N; i++) {new Writer(barrier).start();
}
try {
Thread.sleep(25000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("CyclicBarrier reuse");
for(int i=0; i<N; i++) {newWriter(barrier).start(); }}static class Writer extends Thread{
private CyclicBarrier cyclicBarrier;
public Writer(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run(a) {
System.out.println("Thread"+Thread.currentThread().getName()+"Writing data...");
try {
Thread.sleep(5000); // Use sleep to simulate writing data
System.out.println("Thread"+Thread.currentThread().getName()+"Write data complete, wait for other threads to write data complete.");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
}catch(BrokenBarrierException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"All threads write, continue processing other tasks..."); }}}Copy the code
Output:
Thread the Thread -0Writing data... Thread the Thread -1Writing data... Thread the Thread -3Writing data... Thread the Thread -2Writing data... Thread the Thread -1Wait for other threads to finish writing data Thread-3Wait for other threads to finish writing data Thread-2Wait for other threads to finish writing data Thread-0Waiting for other threads to finish writing data Thread-0All threads write, continue processing other tasks... Thread-3All threads write, continue processing other tasks... Thread-1All threads write, continue processing other tasks... Thread-2All threads write, continue processing other tasks... CyclicBarrier reuses threads Thread-4Writing data... Thread the Thread -5Writing data... Thread the Thread -6Writing data... Thread the Thread -7Writing data... Thread the Thread -7Wait for other threads to finish writing data Thread-5Wait for other threads to finish writing data Thread-6Wait for other threads to finish writing data Thread-4Waiting for other threads to finish writing data Thread-4All threads write, continue processing other tasks... Thread-5All threads write, continue processing other tasks... Thread-6All threads write, continue processing other tasks... Thread-7All threads write, continue processing other tasks...Copy the code
Semaphore
Semaphore can control the number of threads accessed at the same time, acquire a license through acquire(), wait if not, and release() releases a license.
The Semaphore class, located under the java.util.concurrent package, provides two constructors:
public Semaphore(int permits) { // Permitting indicates the number of permits, that is, how many threads are allowed to access at the same time
sync = new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) { // If it is fair, the longer you wait, the sooner you get the license
sync = (fair)? new FairSync(permits) : new NonfairSync(permits);
}
Copy the code
Acquire (); release(); Semaphore ();
Public void acquire() throws InterruptedException {} // Obtain a license public void acquire(int Permits) throws Public void release() {} Public void release(int Permitting) {} // Release permitsAcquire () to acquire a license. If no license can be obtained, wait until a license is obtained.Copy the code
Release () is used to release permissions. Note that permission must be obtained before release.
All four methods block. If you want immediate results, you can use the following methods:
public boolean tryAcquire() { }; // Try to obtain a license, if successful, return true immediately, if failed, False public Boolean tryAcquire(long timeout, TimeUnit Unit) throws InterruptedException {}; Public Boolean tryAcquire(int permits) {} public Boolean tryAcquire(int permits) {} // Attempt to obtain permits, if successful, immediately return true, if failed, False public Boolean tryAcquire(int Permits, long timeout, TimeUnit Unit) throws InterruptedException {}; // Attempt to obtain permits immediately true if successful within the specified time, otherwise immediately falseCopy the code
The number of permits available can also be obtained via the availablePermits() method.
Here’s an example of Semaphore in action:
If a factory has five machines but eight workers, each machine can only be used by one worker at a time, until it is used up, other workers can continue to use it. We can do this with Semaphore:
public class Test {
public static void main(String[] args) {
int N = 8; / / the number of workers
Semaphore semaphore = new Semaphore(5); // Number of machines
for(int i=0; i<N; i++)new Worker(i,semaphore).start();
}
static class Worker extends Thread{
private int num;
private Semaphore semaphore;
public Worker(int num,Semaphore semaphore){
this.num = num;
this.semaphore = semaphore;
}
@Override
public void run(a) {
try {
semaphore.acquire();
System.out.println("Workers"+this.num+"Occupy a machine in production...");
Thread.sleep(2000);
System.out.println("Workers"+this.num+"Unleash the machine.");
semaphore.release();
} catch(InterruptedException e) { e.printStackTrace(); }}}}Copy the code
The execution result
workers0Take up a machine in production... workers1Take up a machine in production... workers2Take up a machine in production... workers4Take up a machine in production... workers5Take up a machine in production... workers0Free up the robot workers2Free up the robot workers3Take up a machine in production... workers7Take up a machine in production... workers4Free up the robot workers5Free up the robot workers1Free up the robot workers6Take up a machine in production... workers3Free up the robot workers7Free up the robot workers6Release the machineCopy the code
Here’s a summary of the three helper classes:
-
Both CountDownLatch and CyclicBarrier enable waiting between threads, but with different emphasis. CountDownLatch is typically used when thread A waits for several other threads to complete their tasks before it executes. A CyclicBarrier is typically used when a group of threads wait for each other to reach a state and then execute simultaneously. In addition, countdownlatches are not reusable, while cyclicBarriers are.
-
Semaphore is similar to a lock in that it is used to control access to a set of resources.
References:
-
Ideas for Java Programming
-
www.itzhai.com/the-introdu…
-
Leaver. Me/archives / 32…
-
Developer.51cto.com/art/201403/…
-
Blog.csdn.net/yanhandle/a…
-
Blog.csdn.net/cutesource/…
-
www.cnblogs.com/whgw/archiv…