Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use Semaphore, CyclicBarrier and CountDownLatch in JUC

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains "how to use Semaphore, CyclicBarrier, CountDownLatch in JUC". The content in the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "how to use Semaphore, CyclicBarrier, CountDownLatch in JUC".

(1) Overview

There are two ways to allocate resources, one is exclusive, such as the ReentrantLock mentioned earlier, and the other is sharing, that is, Semaphore, CyclicBarrier, and CountDownLatch that we are going to learn today. These are the classes in the JUC package.

(2) Semaphore

Semaphore means semaphore and its function is to control the number of threads accessing a particular resource. Its core API is:

Semaphore.acquire (); semaphore.release ()

This may be a bit vague. Let me give you an example.

Semaphore is like the administrator of an amusement facility in an amusement park to control the number of people who play the facility at the same time. For example, if the jumper can only seat ten people, set the permits of Semaphore equal to 10.

Whenever a person comes, first determine whether the permits is greater than 0, if it is greater than 0, give a license to that person, and reduce the number of permits by one.

If the number of permits equals zero, others will have to wait in line when they want to come in.

When a person has finished playing, the person returns the license to Semaphore,permits plus 1, and the people in the queue compete for the license.

Here is a code to demonstrate such a scenario

Public class SemaphoreTest {public static void main (String [] args) {/ / create permits equals 2 Semaphore semaphore=new Semaphore (2); / / open five threads to execute PlayGame for (int I = 0; I

< 5; i++) { new Thread(new PlayGame(semaphore)).start(); } } static class PlayGame extends Thread{ Semaphore semaphore; public PlayGame(Semaphore semaphore){ this.semaphore=semaphore; } @Override public void run() { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName()+"获得一个许可证"); Thread.sleep(1000); System.out.println(Thread.currentThread().getName()+"释放一个许可证"); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } } }} 在这里设置Semaphore的permit等于2,表示同时只有两个线程可以执行,然后开五个线程,在执行前通过semaphore.acquire();获取permit,执行后通过semaphore.release();归还permit。

From the results, it can be observed that at most two threads execute PlayGame at a time.

(3) Semaphore principle 3.1 default unfair lock

By default, Semaphore creates an unfair lock:

3.2 Semaphore source code analysis

Semaphore is implemented in a very similar way to ReentrantLock.

First define an inner class Sync inheriting AbstractQueuedSynchronizer

As you can see from the construction method of Sync, setting state equals permits during initialization, when talking about ReentrantLock, state is used to store the number of reentrant locks, and state is used to store the number of resources in Semaphore.

The core methods of Semaphore are acquire and release. When the acquire method is executed, sync performs an operation to get a shared resource:

The core is to determine whether the remaining quantity is greater than 0. If so, get the resource through the cas operation, otherwise enter the queue and wait.

When the release method is executed, sync performs a cas operation to put a shared resource back

(4) CountDownLatch

Countdownlatch allows one thread to wait for other threads to finish their work before executing.

Countdownlatch is implemented through a counter, the initial value is a specified number, each time a thread completes its own task, the counter is reduced by one, when the counter is 0, the last waiting thread is executed.

Its core API is

CountDownLatch.countDown (); CountDownLatch.await ()

Let's look at the code example:

Set the initial value of countDownLatch to 2, and define two threads to execute the corresponding method respectively, and then execute countDownLatch.countDown () after the method is executed; during the execution of these two methods, the main thread is blocked by countDownLatch.await (), and can only be executed after other threads have finished executing.

Public class CountDownLatchTest {public static void main (String [] args) throws InterruptedException {/ / set the initial value to 2 CountDownLatch countDownLatch=new CountDownLatch (2); / / execute two tasks new Thread (new Task1 (countDownLatch)). Start (); new Thread (new Task2 (countDownLatch)). Start (); / / the code countDownLatch.await () after the await method is executed after the two tasks have been executed System.out.println ("execute after the other two threads execute");} private static class Task1 implements Runnable {private CountDownLatch countDownLatch; public Task1 (CountDownLatch countDownLatch) {this.countDownLatch=countDownLatch;} @ Override public void run () {System.out.println ("execute Task 1") Try {Thread.sleep (2000);} catch (InterruptedException e) {e.printStackTrace ();} finally {if (countDownLatchboxes null) {/ / call countDown countDownLatch.countDown () after execution }} private static class Task2 implements Runnable {private CountDownLatch countDownLatch; public Task2 (CountDownLatch countDownLatch) {this.countDownLatch=countDownLatch;} @ Override public void run () {System.out.println (execute Task II); try {Thread.sleep (3000) } catch (InterruptedException e) {e.printStackTrace ();} finally {if (countDownLatchboxes null) {/ / call countDown countDownLatch.countDown ();} after execution is complete

The effect is as follows:

(5) CyclicBarrier

A fence barrier that blocks a group of threads when they reach a barrier (also known as a synchronization point). The barrier will not open until the last thread reaches the barrier, and all threads blocked by the barrier will not continue to run. Its core API is:

CyclicBarrier.await ()

Unlike countdownlatch, countdownlatch is a thread that waits for other threads to finish execution, while CyclicBarrier is a thread that waits for all threads to finish execution before executing.

Look at the code, the initialization cyclicBarrier is 3, two child threads and one main thread will be blocked in cyclicBarrier.await () when they are finished; before the code, wait until the three threads have finished executing before executing the next code.

Public class CyclicBarrierTest {public static void main (String [] args) throws BrokenBarrierException, InterruptedException {CyclicBarrier cyclicBarrier=new CyclicBarrier (3); System.out.println ("execute main thread"); new Thread (new Task1 (cyclicBarrier)). Start (); new Thread (new Task2 (cyclicBarrier)). Start (); cyclicBarrier.await (); System.out.println ("all three threads have finished executing, continue to execute the main thread") } private static class Task1 implements Runnable {private CyclicBarrier cyclicBarrier; public Task1 (CyclicBarrier cyclicBarrier) {this.cyclicBarrier=cyclicBarrier;} @ Override public void run () {System.out.println (execute Task 1); try {Thread.sleep (2000); cyclicBarrier.await () System.out.println ("all three threads have finished executing, continue with task one");} catch (InterruptedException e) {e.printStackTrace ();} catch (BrokenBarrierException e) {e.printStackTrace ();} private static class Task2 implements Runnable {private CyclicBarrier cyclicBarrier Public Task2 (CyclicBarrier cyclicBarrier) {this.cyclicBarrier=cyclicBarrier;} @ Override public void run () {System.out.println (execute Task II); try {Thread.sleep (2000); cyclicBarrier.await () System.out.println ("all three threads are finished, continue to task 2");} catch (InterruptedException e) {e.printStackTrace ();} catch (BrokenBarrierException e) {e.printStackTrace ();}

The results are as follows:

CyclicBarrier can also be executed repeatedly without having to redefine it.

Public static void main (String [] args) throws BrokenBarrierException, InterruptedException {CyclicBarrier cyclicBarrier=new CyclicBarrier (3); / / first System.out.println ("execute main thread"); new Thread (new Task1 (cyclicBarrier)). Start (); new Thread (new Task2 (cyclicBarrier)). Start (); cyclicBarrier.await (); System.out.println ("all three threads have finished executing, continue to execute the main thread") / / second System.out.println ("execute main thread"); new Thread (new Task1 (cyclicBarrier)) .start (); new Thread (new Task2 (cyclicBarrier)) .start (); cyclicBarrier.await () Thank you for your reading. The above is the content of "how to use Semaphore, CyclicBarrier and CountDownLatch in JUC". After the study of this article, I believe you have a deeper understanding of how to use Semaphore, CyclicBarrier and CountDownLatch in JUC, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report