Several useful concurrency tools are available in the JDK’s concurrency package. The CountDownLatch, CyclicBarrier, and Semaphore utility classes provide a means of controlling the concurrency flow.

A, CountDownLatch

CountDownLatch is a synchronization helper class that runs one or more threads in a waiting state until it completes a set of operations that are being performed in other threads. There are two key methods in CountDownLatch

public void countDown() {}
public boolean await(long timeout, TimeUnit unit){}Copy the code

CountDownLatch is a counter whose constructor needs to specify a value that sets the number of counts. Every time the countDown() method is called, the value decreases by one, and CountDownLatch blocks the thread calling the await() method until the counter value is zero. Imagine a function that requires Thread1, Thread2, Thread3, and Thread4 to count disk sizes of C, D, E, and F respectively. All threads are counted and presented to the main latch for aggregation. CountDownLatch is very easy to complete.

package com.dreyer.javadoc.thread; import java.util.Date; import java.util.Random; import java.util.concurrent.*; /** * @description CountDownLatch * @author: Dreyer * @date: 16/5/14 11:41 PM */ public class CountDownLatchDemo {/** ** / private static CountDownLatch CountDownLatch = new CountDownLatch(4); / * * * * thread pool/private static ExecutorService executor. = Executors newFixedThreadPool (4); Private static int THREAD_COUNT = 1; public static void main(String[] args) throws InterruptedException { for (int i = 0; i < THREAD_COUNT; I++) {executor.execute(new Runnable() {public void run() {try {// time spent simulating service logic int timer = new Random().nextint (5); TimeUnit.SECONDS.sleep(timer); Printf ("%s ", new Date().toString(), timer); system.out.printf ("%s ", new Date().tostring (), timer); Countdownlatch.countdown (); countdownlatch.countdown (); } catch (InterruptedException e) { e.printStackTrace(); }}}); } // The main thread is blocked until countDownLatch is 0 countdownlatch.await (); System.out.printf("%s ", new Date().toString()); executor.shutdown(); }}Copy the code

Second, the CyclicBarrier

All a CyclicBarrier does is block a group of threads as they reach a barrier (also known as a synchronization point) until the last thread reaches the barrier and the barrier opens and all threads blocked by the barrier continue to run. When a CyclicBarrier is initialized, a barrier number is set. When a thread calls await(), the thread is blocked, and when the number of threads calling await() reaches the barrier, the main thread unstates all blocked threads. Its construction method is as follows:

public CyclicBarrier(int parties){}Copy the code

The parties argument also provides a more advanced constructor for the number of barriers at initialization CyclicBarrier

public CyclicBarrier(int parties, Runnable barrierAction) {}Copy the code

The barrierAction is used to preferentially execute barrierAction when the thread reaches the barrier, which is convenient for processing more complex business scenarios. For example, an Excel is used to store all the bank statements of the user, and each sheet is used to store every transaction statement of an account in the last year. Now the average daily transaction statement of the user needs to be counted. First, multithreading is used to process the transaction flow in each sheet, and then the daily average transaction flow of each sheet is obtained after all processing. Finally, barrierAction is used to calculate the daily average bank flow of the whole Excel with the calculation results of these threads, the code is as follows:

package com.dreyer.javadoc.thread; import java.util.Map; import java.util.concurrent.*; @author: Dreyer * @date: 16/5/15 am 11:29 */ public class BankWaterService implements Runnable {/** * Public class BankWaterService implements Runnable {/** * Public class BankWaterService implements Runnable CyclicBarrier cyclicBarrier = new CyclicBarrier(4, this); / * * * start four threads * / private Executor Executor = Executors. NewFixedThreadPool (4); /** * Private ConcurrentHashMap<String, Integer> sheetBankWaterCount = new ConcurrentHashMap<String, Integer>(); /** * private void count() {for (int I = 0; i < 4; I++) {executor.execute(new Runnable() {public void run() {// simulate the transaction processing of the current sheet sheetBankWaterCount.put(Thread.currentThread().getName(), 1); // Insert a barrier try {cyclicBarrier. Await (); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); }}}); Public void run() {int result = 0; for (Map.Entry<String, Integer> sheet : sheetBankWaterCount.entrySet()) { result += sheet.getValue(); } // Set the result and print sheetBankWaterCount. Put ("result", result); System.out.println(result); } public static void main(String[] args) { BankWaterService service = new BankWaterService(); service.count(); }}Copy the code

Third, Semapphore

Semaphore is used to control the number of threads accessing a given resource at the same time by coordinating threads to ensure that the resource is properly used. As an analogy, Semaphore is like a traffic light that controls the flow of traffic. For example, if xx Road requires the current flow of traffic, only one hundred cars are allowed to drive on the road at the same time, and the other cars must wait at the intersection. Therefore, the first hundred cars will see the green light and can enter the road, while the ones behind will see the red light and cannot enter the road. But if 5 of the 100 cars in front have left the road, then 5 cars behind are allowed to enter the road. In this example, the car is the thread. If the car enters the road, the thread is executing, and if it leaves the road, the thread is finished. Application Scenarios Semaph can be used for traffic limiting, especially when common resources are limited, such as database connections. If there is a demand, want to read tens of thousands of file data, because is IO intensive character, we can start the dozens of threads concurrent read, but if after read into memory, also need to be stored into the database, and database connections only 10, this time we have to control only 10 threads at the same time, access to the database connection, Otherwise, an exception is thrown indicating that the database cannot be connected. In this case, we can use Semaphore for flow control. The code is as follows:

package com.dreyer.javadoc.thread; import java.util.concurrent.*; /** * @description * @author: Dreyer * @date: 16/5/15 am 11:59 */ public class SemaphoreDemo {private static final int THREAD_COUNT = 30; / * * * * thread pool/private static ExecutorService executor. = Executors newFixedThreadPool (THREAD_COUNT); private static Semaphore semaphore = new Semaphore(10); public static void main(String[] args) { for (int i = 0; i < THREAD_COUNT; I++) {executor.execute(new Runnable() {public void run() {try {// acquire a "license" semaphore.acquire(); Timeunit.seconds.sleep (2); System.out.println("save date..." ); // return "license" semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); }}}); } executor.shutdown(); }}Copy the code

In the code, there are 30 threads executing, but only 10 concurrent executions are running. So we can see in the execution

save data… It goes out every 10.

Semaphore(int permits) accepts an integer indicating the number of permits available.

Semaphore(10) means to run 10 threads to obtain the license, i.e., the maximum concurrency is 10.

Semaphore is also simple to use. First use the Semaphore.acquire() method to obtain a license and then call it

The release() method returns the license.

  • give a like
  • collection
  • share
    • The article reported


The corner of happiness
Direct messages
Focus on