Java Concurrency Programming: Countdownlatch, Cyclicbarrier, and semaphore

Source: Internet
Author: User
Tags semaphore

Java Concurrency Programming: Countdownlatch, Cyclicbarrier, and semaphore

In Java 1.5, there are some very useful helper classes to help us with concurrent programming, such as Countdownlatch,cyclicbarrier and semaphore, and today we'll learn about the use of these three helper classes.

The following is an outline of this article directory:

I. Countdownlatch usage

Two. Cyclicbarrier usage

Three. Semaphore usage

If there are any shortcomings please understand, and welcome criticism.


  

I. Countdownlatch usage

The Countdownlatch class is located under the Java.util.concurrent package and can be used to implement similar counter functions. For example, there is a task a, which waits for the other 4 tasks to be executed before they can be executed, and this is done using Countdownlatch.

The Countdownlatch class provides only one constructor:

public Countdownlatch (int count) {}; Parameter count is a count value

Then the following 3 methods are the most important methods in the Countdownlatch class:

public void await () throws interruptedexception {}; The thread that calls the await () method is suspended, and it waits until the count value is 0 to continue executing public boolean await (long timeout, timeunit unit) throws Interruptedexception  { };  Similar to await (), except for a certain amount of time after which the count value has not changed to 0 will continue to execute public void Countdown () {}; Subtract the count value by 1

Let's look at an example and see how Countdownlatch is used:

Public class test { public static void main (String[] args)  {      final countdownlatch latch = new countdownlatch (2);   new thread () { public void run ()  { try { system.out.println ("Child Thread" +thread.currentthread (). GetName () + "executing"); 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 ()  { try {  SYSTEM.OUT.PRINTLN ("Child Thread" +thread.currentthread (). GetName () + "executing");  thread.sleep (; ) SYSTEM.OUT.PRINTLN ("Child Thread" +thread.currentthread (). GetName () + "executed");  latch.countdown ();  catch  (interruptedexception e)  {e.printstacktrace ();}  }; }.start ();   try { system.out.println ("Wait 2Sub-thread execution complete ... "); latch.await (); System.out.println ("2 sub-threads have been executed"); System.out.println ("Continue with the main thread");}  catch  (interruptedexception e)  {e.printstacktrace ();}  } }

Execution Result:

Thread Thread-0 is executing thread Thread-1 is executing waiting for 2 sub-threads to finish executing ... Thread Thread-0 execution completed thread Thread-1 execution completed 2 sub-threads have been executed continue to execute the main thread

View Code

Two. Cyclicbarrier usage

Literally, the loopback fence, which allows a group of threads to wait until a certain state has been executed. The loopback is called because Cyclicbarrier can be reused when all waiting threads are freed. Let's call this state barrier, and when the await () method is called, the thread is barrier.

The Cyclicbarrier class is located under the Java.util.concurrent package and Cyclicbarrier provides 2 constructors:

public Cyclicbarrier (int parties, Runnable barrieraction) {}public cyclicbarrier (int parties) {}

The parameter parties refers to how many threads or tasks wait to the barrier state, and the parameter barrieraction the content that will be executed when those threads reach the barrier state.

Then the most important method in Cyclicbarrier is the await method, which has 2 overloaded versions:

public int await () throws Interruptedexception, brokenbarrierexception {};p ublic int await (long timeout, timeunit unit) th Rows Interruptedexception,brokenbarrierexception,timeoutexception {};

The first version is more commonly used to suspend the current thread until all threads reach the barrier state and perform subsequent tasks simultaneously;

The second version is to allow these threads to wait for a certain amount of time, and if the thread does not reach the barrier state, then the threads that reach barrier will perform the subsequent tasks directly.

Here are a few examples to understand:

If there are a number of threads that are going to write data, and only after all the threads have completed the write data operation, the threads can continue to do the following, and the Cyclicbarrier is now available:

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 ();}  static class Writer extends Thread{private CyclicBarrier cyclicBarrier; Public writer (Cyclicbarrier cyclicbarrier)  {this.cyclicbarrier = cyclicbarrier;} @Overridepublic  void run ()  {system.out.println ("Thread" +thread.currentthread (). GetName () + "writing data ... Try {thread.sleep ("      //"); System.out.println ("thread" +) that simulates the write data operation with sleep Thread.CurrentThread (). GetName () + "Write data complete, wait for other threads to finish writing"); cyclicbarrier.await ();}  catch  (interruptedexception e)  {e.printstacktrace ();} catch (brokenbarrierexception e) {e.printstacktrace ();} System.out.println ("All threads have finished writing, continue processing other tasks ...");}}} 

Execution Result:

Thread Thread-0 is writing data ... Thread Thread-3 is writing data ... Thread Thread-2 is writing data ... Thread Thread-1 is writing data ... The thread Thread-2 writes the data, waits for the other thread to finish writing the thread Thread-0 writes the data, waits for the other thread to finish writing the thread Thread-3 writes the data, waits for the other thread to complete the thread Thread-1 writes the data completes, Wait for other threads to finish writing all of the threads and continue processing other tasks ... All threads have finished writing and continue to handle other tasks ... All threads have finished writing and continue to handle other tasks ... All threads have finished writing and continue to handle other tasks ...

View Code

As you can see from the output above, each write thread waits for another thread to write after the write operation has finished.

After all thread-thread-write operations are complete, all threads continue to perform subsequent operations.

If you want to do extra work after all the thread writes have been done, you can provide the runnable parameter for Cyclicbarrier:

Public class test {public static void main (String[] args)  {int N  = 4; Cyclicbarrier barrier  = new cyclicbarrier (n,new runnable ()  {@ Overridepublic void run ()  {system.out.println ("Current Thread" +thread.currentthread (). GetName ());}); for (int i=0;i<n;i++) New writer (barrier). Start ();}  static class Writer extends Thread{private CyclicBarrier cyclicBarrier; Public writer (Cyclicbarrier cyclicbarrier)  {this.cyclicbarrier = cyclicbarrier;} @Overridepublic  void run ()  {system.out.println ("Thread" +thread.currentthread (). GetName () + "writing data ... Try {thread.sleep ("      //"); System.out.println ("thread" +) that simulates the write data operation with sleep Thread.CurrentThread (). GetName () + "Write data complete, wait for other threads to finish writing"); cyclicbarrier.await ();}  catch  (interruptedexception e)  {e.printstacktrace ();} catch (Brokenbarrierexception&nbsP;e) {e.printstacktrace ();} System.out.println ("All threads are finished writing, continue processing other tasks ...");}}}

Operation Result:

Thread Thread-0 is writing data ... Thread Thread-1 is writing data ... Thread Thread-2 is writing data ... Thread Thread-3 is writing data ... The thread Thread-0 writes the data, waits for the other thread to finish writing the thread Thread-1 writes the data, waits for the other thread to finish writing the thread Thread-2 writes the data, waits for the other thread to complete the thread Thread-3 writes the data completes, Wait for other threads to finish writing the current thread Thread-3 all threads have finished writing, continue processing other tasks ... All threads have finished writing and continue to handle other tasks ... All threads have finished writing and continue to handle other tasks ... All threads have finished writing and continue to handle other tasks ...

View Code

As you can see from the results, when four threads reach the barrier state, a thread is selected from four threads to execute the runnable.

Let's take a look at the effect of specifying the time for await:

Public class test {public static void main (String[] args)  {int N  = 4; Cyclicbarrier barrier  = new cyclicbarrier (N); for (int i=0;i<n;i++)  {if (i <n-1) New writer (barrier). Start (); Else {try {thread.sleep (5000);}  catch  (interruptedexception e)  {e.printstacktrace ();} New writer (barrier). Start ();}}}  static class Writer extends Thread{private CyclicBarrier cyclicBarrier; Public writer (Cyclicbarrier cyclicbarrier)  {this.cyclicbarrier = cyclicbarrier;} @Overridepublic  void run ()  {system.out.println ("Thread" +thread.currentthread (). GetName () + "writing data ... Try {thread.sleep ("      //"); System.out.println ("thread" +) that simulates the write data operation with sleep Thread.CurrentThread (). GetName () + "Write data complete, wait for other threads to finish writing") Try {cyclicbarrier.await (2000,  Timeunit.milliseconds);}  catch  (Timeoutexception e)  {// todo auto-generated catch blocke.printstacktrace ();}}  catch  (interruptedexception e)  {e.printstacktrace ();} catch (brokenbarrierexception e) {e.printstacktrace ();} System.out.println (Thread.CurrentThread (). GetName () + "All threads have finished writing, continue processing other tasks ...");}}

Execution Result:

Thread Thread-0 is writing data ... Thread Thread-2 is writing data ... Thread Thread-1 is writing data ... The thread Thread-2 writes the data, waits for the other thread to finish writing the thread Thread-0 writes the data, waits for the other thread to finish writing the thread Thread-1 writes the data, waits for the other thread to finish writing the thread Thread-3 is writing the data ... Java.util.concurrent.timeoutexceptionthread-1 All threads have finished writing, continue processing other tasks ... Thread-0 All threads are finished writing, continue processing other tasks ...     at java.util.concurrent.cyclicbarrier.dowait (Unknown  source)     at java.util.concurrent.cyclicbarrier.await (Unknown Source)     at com.cxh.test1.test$writer.run (test.java:58) java.util.concurrent.brokenbarrierexception    at  Java.util.concurrent.CyclicBarrier.dowait (Unknown source)     at  Java.util.concurrent.CyclicBarrier.await (Unknown source)     at  Com.cxh.test1.test$writer.run (test.java:58) java.util.concurrent.brokenbarrierexception     At java.util.concurrent.cyclicbarrier.dowait (Unknown source)     at  Java.util.concUrrent. Cyclicbarrier.await (Unknown source)     at com.cxh.test1.test$writer.run ( test.java:58) Thread-2 all threads to finish writing, continue to work on other tasks ... Java.util.concurrent.BrokenBarrierException thread Thread-3 writes data, waits for other threads to finish writing     at  Java.util.concurrent.CyclicBarrier.dowait (Unknown source)     at  Java.util.concurrent.CyclicBarrier.await (Unknown source)     at  Com.cxh.test1.test$writer.run (test.java:58) Thread-3 All threads finish writing, continue to work on other tasks ...

View Code

The above code deliberately lets the last thread start the delay in the for loop of the main method, because after the previous three threads have reached barrier, waiting for the specified time to discover that the fourth thread has not reached barrier, throws an exception and continues with the subsequent task.

In addition Cyclicbarrier can be reused, see the following 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++)  {new writer (barrier). Start ();}}  static class Writer extends Thread{private CyclicBarrier cyclicBarrier; Public writer (Cyclicbarrier cyclicbarrier)  {this.cyclicbarrier = cyclicbarrier;} @Overridepublic  void run ()  {system.out.println ("Thread" +thread.currentthread (). GetName () + "writing data ... Try {thread.sleep ("      //"); System.out.println ("thread" +) that simulates the write data operation with sleep Thread.CurrentThread (). GetName () + "Write data complete, wait for other threads to finish writing"); cyclicbarrier.await ();}  catch  (interruptedexception e)  {e.printstacktrace ();} catch (brokenbarrierexception e) {e.printstacktrace ();} System.out.println (Thread.CurrentThread (). GetName () + "All threads have finished writing, continue processing other tasks ...");}}

Execution Result:

Thread Thread-0 is writing data ... Thread Thread-1 is writing data ... Thread Thread-3 is writing data ... Thread Thread-2 is writing data ... The thread Thread-1 writes the data, waits for the other thread to finish writing the thread Thread-3 writes the data, waits for the other thread to finish writing the thread Thread-2 writes the data, waits for the other thread to complete the thread Thread-0 writes the data completes, Wait for other threads to finish writing Thread-0 All threads are finished writing, continue processing other tasks ... Thread-3 All threads have finished writing, continue processing other tasks ... Thread-1 All threads have finished writing, continue processing other tasks ... Thread-2 All threads have finished writing, continue processing other tasks ... Cyclicbarrier reusing thread Thread-4 writing data ... Thread Thread-5 is writing data ... Thread Thread-6 is writing data ... Thread Thread-7 is writing data ... The thread Thread-7 writes the data, waits for the other thread to finish writing the thread Thread-5 writes the data, waits for the other thread to finish writing the thread Thread-6 writes the data, waits for the other thread to complete the thread Thread-4 writes the data completes, Wait for other threads to finish writing Thread-4 All threads are finished writing, continue processing other tasks ... Thread-5 All threads have finished writing, continue processing other tasks ... Thread-6 All threads have finished writing, continue processing other tasks ... Thread-7 All threads have finished writing, continue processing other tasks ...

View Code

As can be seen from the execution results, after the first 4 threads have crossed the barrier state, they can be used for a new round of use. And Countdownlatch cannot be reused.

Three. Semaphore usage

Semaphore translates into a semaphore, Semaphore can control the number of simultaneous accesses, obtain a license through acquire (), and if no wait, release () releases a license.

The Semaphore class is located under the Java.util.concurrent package, which provides 2 constructors:

public Semaphore (int permits) {///parameter permits represents the number of licenses, that is, how many threads can be allowed to access sync = new Nonfairsync (permits);} public Semaphore (int permits, Boolean fair) {//This is more than one parameter fair indicates whether it is fair, that is, the longer the wait time, the first to obtain the License Sync = (FAIR)? New Fairsync (Perm Its): New Nonfairsync (permits);}

Here are some of the more important methods in the semaphore class, the first is the acquire (), Release () method:

public void Acquire () throws Interruptedexception {}//get a license public void acquire (int permits) throws Interruptedexce ption {}//Get permits License public void release () {}//release a license public void release (int permits) {}//release permits License

Acquire () is used to obtain a license that, if obtained without permission, waits until the license is granted.

Release () is used for releasing the license. Note that permission must be granted before releasing the license.

These 4 methods will be blocked, if you want to get the results immediately, you can use the following methods:

public Boolean Tryacquire () {}; Attempt to obtain a license that, if successful, returns true immediately, and returns Falsepublic Boolean tryacquire (long timeout, timeunit unit) immediately if the acquisition fails throws  interruptedexception {}; An attempt is made to obtain a license that returns true immediately if it succeeds within the specified time, or returns falsepublic boolean tryacquire (int permits) {} immediately; Attempt to obtain permits license, if successful, returns true immediately, returns Falsepublic boolean tryacquire (int permits, long timeout, timeunit unit) if the acquisition fails Throws Interruptedexception {}; An attempt was made to obtain a permits license that returns true immediately if it succeeds within the specified time, or returns false immediately.

You can also get the number of licenses available through the Availablepermits () method.

Let's take a look at the specific use of semaphore in the following example:

If there are 5 machines in a factory, but there are 8 workers, one machine can only be used by one worker, and the other workers can continue to use it only after the use is finished. Then we can make it through semaphore:

public class Test {public static void main (string[] args) {int N = 8; 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;} @Overridepublic void Run () {try {semaphore.acquire (); System.out.println ("Worker" +this.num+ "occupies a machine in production ..."); Thread.Sleep (2000); System.out.println ("Worker" +this.num+ "releasing the Machine"); Semaphore.release ();} catch (Interruptedexception e) {e.printstacktrace ();}}}}

Execution Result:

Worker 0 occupies a machine in production ... Worker 1 occupies a machine in production ... Worker 2 occupies a machine in production ... Worker 4 occupies a machine in production ... Worker 5 occupies a machine in production ... The worker 0 released the machine Worker 2 released the machine worker 3 occupied a machine in production ... Worker 7 occupies a machine in production ... The worker 4 released the machine worker 5 released the machine worker 1 released the machine worker 6 occupied a machine in production ... Worker 3 releases the machine worker 7 releases the machine worker 6 releases the machine

View Code

  

Here is a summary of the three auxiliary classes mentioned above:

1) Countdownlatch and Cyclicbarrier are capable of waiting between threads, except that they focus differently:

Countdownlatch is typically used when a thread a waits for several other threads to finish executing a task before it executes;

And Cyclicbarrier is generally used for a group of threads to wait for each other to a certain state, then this group of threads execute concurrently;

In addition, Countdownlatch cannot be reused, and cyclicbarrier can be reused.

2) Semaphore is actually a bit like a lock, which is typically used to control access to a group of resources.

Please respect the author's labor results, reproduced please indicate the original link:

Http://www.cnblogs.com/dolphin0520/p/3920397.html

  

Resources:

The idea of Java programming

Http://www.itzhai.com/the-introduction-and-use-of-a-countdownlatch.html

Http://leaver.me/archives/3220.html

Http://developer.51cto.com/art/201403/432095.htm

http://blog.csdn.net/yanhandle/article/details/9016329

http://blog.csdn.net/cutesource/article/details/5780740

Http://www.cnblogs.com/whgw/archive/2011/09/29/2195555.html

Java Concurrency Programming: Countdownlatch, Cyclicbarrier, and semaphore

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.