preface

Before learning multithreading, there was no synchronization tool class for learning threads (helper class). Ps: AT that time, I felt that I could not use it temporarily. I thought it was a very advanced knowledge point and did not take care of it.

A few days ago, my friend sent me a good Semaphore article, and then when browsing the blog, I found that the interview will be taken, which is still quite important knowledge. So I took the time to find out.

Java provides us with three synchronization utility classes:

  • CountDownLatch (lock)
  • CyclicBarrier (fence)
  • Semaphore

The purpose of these tools is to control communication between threads

A, CountDownLatch

1.1 CountDownLatch profile

  • A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

Simply put: CountDownLatch is a synchronous helper class that allows one or more threads to wait until other threads have completed their work.

It uses two apis :await() and countDown()

Instructions:

  • Count initializes CountDownLatch, and the waiting thread calls the await method. The await method will block until count=0. While other threads finish their operations, callcountDown()Decrement the counter count by 1.When count falls to 0, all waiting threads are released
  • The count variable is used to control the wait, and if count is 0 (all other threads have completed their work), the execution can continue.

1.2 CountDownLatch example

Example: 3Y is working as an intern now, but the other employees are not off duty yet. 3Y is embarrassed to leave first. She will leave after all the other employees are gone.


import java.util.concurrent.CountDownLatch;

public class Test {

    public static void main(String[] args) {

        final CountDownLatch countDownLatch = new CountDownLatch(5);

		System.out.println("Now off work at 6.....");

        // the 3y thread starts
        new Thread(new Runnable() {
            @Override
            public void run(a) {
           
                try {
                    Call await() instead of wait()
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("... With the other five employees gone, 3Y can finally go.");
            }
        }).start();

        // Other employee threads start
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run(a) {
                    System.out.println("Employee XXXX is off duty."); countDownLatch.countDown(); } }).start(); }}}Copy the code

Output result:

Another example: 3Y is now in charge of warehouse module functions, but his ability is so poor that he writes very slowly. Other employees need to wait for 3Y to finish writing before they can continue to write.


import java.util.concurrent.CountDownLatch;

public class Test {

    public static void main(String[] args) {

        final CountDownLatch countDownLatch = new CountDownLatch(1);

        // the 3y thread starts
        new Thread(new Runnable() {
            @Override
            public void run(a) {

                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("3Y finally finished.");
                countDownLatch.countDown();

            }
        }).start();

        // Other employee threads start
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run(a) {
                    System.out.println("Other employees need to wait for 3Y");
                    try {
                        countDownLatch.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("3Y is finally finished and the rest of the staff can get started!"); } }).start(); }}}Copy the code

Output result:

References:

  • Blog.csdn.net/qq_19431333…
  • Blog.csdn.net/panweiwei19…
  • www.importnew.com/15731.html

Second, the CyclicBarrier

2.1 CyclicBarrier profile

  • A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.

Simply put: A CyclicBarrier allows a group of threads to wait for each other until some common barrier point is reached. CyclicBarrier is called cyclic because CyclicBarrier can be reused (as opposed to CountDownLatch, which is not reused) after all waiting threads have been released.

Instructions:

  • CountDownLatch is about waiting for other threads to complete, CyclicBarrier is about pausing when a thread reaches a state, waiting for other threads to complete, and resuming execution when all threads have arrived.

2.2 CyclicBarrier example

Example: 3Y and his girlfriend made an appointment to go to Guangzhou for dinner in Shanghai. Since 3Y and his girlfriend live in different places, the natural way to go is also different. So they agreed to meet at the Subway station of Tiyu West Road, and agreed to send a message to each other when they met.


import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Test {

    public static void main(String[] args) {

        final CyclicBarrier CyclicBarrier = new CyclicBarrier(2);
        for (int i = 0; i < 2; i++) {

            new Thread(() -> {

                String name = Thread.currentThread().getName();
                if (name.equals("Thread-0")) {
                    name = "3y";
                } else {
                    name = "Girlfriend";
                }
                System.out.println(name + "To Sports West.");
                try {

                    // Both of us have to go to Sports West to post on wechat
                    CyclicBarrier.await();
                    // When they arrived at Tiexi, they saw each other and posted a message on wechat:
                    System.out.println("With" + name + "To eat at night.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch(BrokenBarrierException e) { e.printStackTrace(); } }).start(); }}}Copy the code

Test results:

After playing for a day, they returned home. 3Y and his girlfriend agreed to chat after taking a shower


import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Test {

    public static void main(String[] args) {

        final CyclicBarrier CyclicBarrier = new CyclicBarrier(2);
        for (int i = 0; i < 2; i++) {

            new Thread(() -> {

                String name = Thread.currentThread().getName();
                if (name.equals("Thread-0")) {
                    name = "3y";
                } else {
                    name = "Girlfriend";
                }
                System.out.println(name + "To Sports West.");
                try {

                    // Both of us have to go to Sports West to post on wechat
                    CyclicBarrier.await();
                    // When they arrived at Tiexi, they saw each other and posted a message on wechat:
                    System.out.println("With" + name + "To eat at night.");

                    / / home
                    CyclicBarrier.await();
                    System.out.println(name + "Shower");

                    // Chat together after taking a shower
                    CyclicBarrier.await();

                    System.out.println("Talk together.");

                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch(BrokenBarrierException e) { e.printStackTrace(); } }).start(); }}}Copy the code

Test results:

References:

  • Blog.csdn.net/panweiwei19…

Third, Semaphore

3.1 introduction of Semaphore

Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource.


  • A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each {@link #acquire} blocks if necessary until a permit is available, and then takes it. Each {@link #release} adds a permit,potentially releasing a blocking acquirer.However, no actual permit objects are used; the {@code Semaphore} just keeps a count of the number available and acts accordingly.

A Semaphore is essentially a control over the number of threads accessed at the same time. It maintains a set of **” licenses “**.

  • When callingacquire()Method, a license is consumed. If there is no permit, it will be blocked
  • When callingrelease()Method, a license is added.
  • The number of “licenses” is just a count variable

3.2 Semaphore example

3Y’s girlfriend owns a yogurt shop. The shop can only accommodate 5 customers at a time. If more than 5 customers choose to buy yogurt, they have to wait in line



import java.util.concurrent.Semaphore;

public class Test {

    public static void main(String[] args) {

        // Suppose there are 50 at the same time
        int nums = 50;

        // The yogurt shop can only hold 10 people at a time
        Semaphore semaphore = new Semaphore(10);

        for (int i = 0; i < nums; i++) {
            int finalI = i;
            new Thread(() -> {
                try {
                    // Only those with a "size" can enter the yogurt shop
                    semaphore.acquire();

                    System.out.println("Customer" + finalI + "Looking for goods, buying...");

                    // Suppose you have picked xx for a long time and bought it
                    Thread.sleep(1000);

                    // Return a license and the following can be purchased
                    System.out.println("Customer" + finalI + "Purchase done...");
                    semaphore.release();



                } catch(InterruptedException e) { e.printStackTrace(); } }).start(); }}}Copy the code

Output result:

Anyway, only five customers can go into the yogurt shop at a time.

References:

  • Blog.csdn.net/qq_19431333…
  • Blog.csdn.net/panweiwei19…

Four,

Java provides us with three synchronization utility classes:

  • CountDownLatch (lock)
    • A thread waits for other threads to finish executing before it executes.
  • CyclicBarrier (fence)
    • A group of threads waits for each other to reach a certain state, and then the group of threads executes simultaneously.
  • Semaphore
    • Controls a group of threads executing simultaneously.

This article briefly introduces the three synchronization utility classes are used, to further look at the source code or reference other materials.

Last but not least, mind mapping:

References:

  • Java Concurrent Programming
  • www.cnblogs.com/dolphin0520…
  • zhuanlan.zhihu.com/p/27829595

If the article has the wrong place welcome to correct, everybody exchanges with each other. Students who are used to reading technical articles on wechat and want to get more Java resources can follow the wechat public account :Java3y.

Article table of Contents navigation:

  • Zhongfucheng.bitcron.com/post/shou-j…