Hello, my name is Semaphore, my Chinese name is “Semaphore”, I come from JUC (java.util.Concurrent) family.

We have a lot of great people in the family like CountDownLatch and CyclicBarrier, but I’m as good as they are.

The following is my personal resume, I hope you give a good comment and three consecutive readers, thank you in this ~

The basic information

  • Name: Semaphore
  • Chinese name :(count) semaphore
  • Date of birth: JDK 1.5
  • Native Place: JUC (java.util.concurrent)
  • USES: Semaphore is a synchronizer in Java. Unlike CountDownLatch and CyclicBarrier, Semaphore is used to manage licenses. If a thread does not have a license when it calls acquire(), it will block and wait. We can’t proceed until we have a permit. Licenses are published using the release() method (publishing a license). When acquire() is called, the license is reduced if there is a certificate and the rest of the code is executed. If there is no certificate, the Semaphore blocks waiting for licenses.

Professional skills

My professional skill is “management certificate”, using this skill can easily achieve “flow limiting” function.

What is current limiting?

Such as the five small long vacation is coming soon, then there will be a lot of people go to the scenic spot, but can accommodate each scenic spot is limited, such as big xi ‘an datang lotus park, its bearing capacity is 60000, that is to say, every day to make a maximum of 60000 people to visit here, but the May Day will come when a lot of people, such as came to 100000 people, At that time, they can only “limit the flow” and wait in line to enter the park.In other words, datang Lotus Garden will let 60,000 people go in first, the rest of the people wait in line at the gate, when someone comes out of the inside, only to allow another person in line to go in. The staff will always control the number of people under 60,000, the purpose of doing so is to let the people have a good experience, not to cause some accidents, such as the stampede, to a certain extent to ensure the stability of the society, but also to facilitate the establishment of a good reputation of the scenic spot and the normal operation in the future, andThe practice of limiting the maximum number of people in a queue is called “flow limiting.”.

Take another example, for example, to limit the number of vehicles, it is also a common scenario of limiting the flow. On the one hand, it can protect the environment and reduce carbon emissions as much as possible; on the other hand, it can effectively alleviate the congestion during peak hours. Especially in Big Xi ‘an, it is hard to imagine if the number is not limited, then what will be blocked? (PS: Let the originally not rich life is worse…)Let’s return to the program from the examples in life, suppose that a program can only provide services for 10W people, suddenly one day because of a hot event, caused the system in a short period of time quickly increased to 50W, then the direct result is the system crash, no one can use the system, It’s clear that having a small number of people using it is much more desirable than having nobody using it, so at this point we’re going to have to limit the flow.

Use Semaphore to implement flow limiting

Semaphore can be created by setting the number of certificates, which is equivalent to setting the maximum flow limiting function. Then, Semaphore can issue certificates through release() and block and wait for certificates through acquire(). Thus, Semaphore can control the flow limiting function by controlling certificates.

Experience in project

Next, let’s demonstrate the use of Semaphore in code. Let’s take the example of limiting the flow of a parking lot. Let’s assume that there are only 2 parking Spaces in the parking lot (a small number of parking Spaces, but suffice it to say), but there are 5 cars in the parking lot. Obviously, there is not enough parking space. The specific implementation code is as follows:

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/** * Author: Lei Ge * By: Java Chinese community */
public class SemaphoreExample {
    // Create a semaphore
    static Semaphore semaphore = new Semaphore(2);

    public static void main(String[] args) {

        // Create a fixed number of threads
        ExecutorService threadPool = Executors.newFixedThreadPool(5);

        // Define the execution task
        Runnable runnable = new Runnable() {
            @Override
            public void run(a) {
                // Get the name of the current thread
                String tname = Thread.currentThread().getName();
                System.out.println(String.format("Old driver: %s, queuing outside the parking lot, time: %s",
                        tname, new Date()));
                try {
                    // Execute this line and have all lines line up to enter the parking lot
                    Thread.sleep(100);
                    // Perform blocking
                    semaphore.acquire();
                    System.out.println(String.format("Old driver: %s, entered the parking lot, time: %s",
                            tname, new Date()));
                    Thread.sleep(1000);
                    System.out.println(String.format("Old driver: %s, leave parking lot, time: %s",
                            tname, new Date()));
                    / / releases the lock
                    semaphore.release();
                } catch(InterruptedException e) { e.printStackTrace(); }}};// Execute task 1
        threadPool.submit(runnable);

        // Execute Task 2
        threadPool.submit(runnable);

        // Execute Task 3
        threadPool.submit(runnable);

        // Execute Task 4
        threadPool.submit(runnable);

        // Perform Task 5
        threadPool.submit(runnable);

        // Close the thread pool after the task is completedthreadPool.shutdown(); }}Copy the code

The execution result of the above code is as follows:From the above results, we can see that when 5 cars need to enter the parking lot at the same time, because there are only 2 parking Spaces in the parking lot, the parking lot can only accommodate 2 cars at most. At this time, we successfully implemented the flow limiting function through Semaphore acquire method (blocking and waiting) and release method (issuing a certificate), so that the number of cars in the parking lot was always controlled below 2 cars (equal to or less than 2 cars).

Personal assessment

Semaphore (Semaphore) has two types of certificate control, one is fair mode and the other is not fair mode. Of course, for the performance of the implementation, I take the non-fair mode by default.

public Semaphore(int permits) {
    sync = new NonfairSync(permits); // Unfair model
}
Copy the code

About the fair model and the unfair model

The so-called fair mode is to call acquire() in order to determine the order of the license, the fair mode follows the first in first out (FIFO) principle; The non-fair mode is preemptive, meaning that it is possible for a new fetching thread to get a license just as it is being released, with waiting threads in front of it.

Obviously, using the unfair mode is more performance, because it permits the threads that are just ready, instead of having to “call” them in order.

Use the fair model

Of course, you can manually choose to run Semaphore in fair mode. Semaphore provides two constructors. The source code is as follows:

public Semaphore(int permits) {
    sync = new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) {
    sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
Copy the code

Permits, Boolean fair); Semaphore(int permits, Boolean fair); set fair to true;

Other supplementary

I’ve also provided some other ways to achieve more functionality, as follows:

  • Int availablePermits() : returns the number of licenses currently available in this semaphore.
  • Int getQueueLength() : returns the number of threads waiting to get a license.
  • Boolean hasQueuedThreads() : Specifies whether any threads are waiting to get a license.
  • Boolean isFair() : Queries whether Semaphore is in fair or non-fair mode. Returns true if the Semaphore is in fair mode.
  • Void release(int permits) : releases a given number of licenses and returns them to the semaphore.
  • TryAcquire () : Obtain a license from this semaphore that can only be used when called.
  • TryAcquire (int permits) : obtain a given number of permits from this semaphore, all of which are only available when invoked.
  • TryAcquire (int permits, Long Timeout, TimeUnit Unit) : Obtain a given number of permits from this semaphore if all are available within a given wait time and the current thread is not interrupted.
  • TryAcquire (Long Timeout, TimeUnit Unit) : If available for a given wait time and the current thread has not yet reached interrupted, a permit is obtained from this semaphore.
  • Void reducePermits(int Reduction) : Reduce the number of permits available, it is protected.
  • Collection getQueuedThreads() : Returns a Collection of all threads waiting to receive a license. It is protected.

conclusion

A Semaphore is used to manage a set of certificates, and by default it does so in an unfair way for high performance. Semaphore contains two important methods: release() publishes a license certificate; The acquire() method blocks and waits for a certificate. When a thread calls acquire(), it can proceed only if it has a certificate, so you can use Semaphore to limit streams.

Check out the Java Chinese Community for more interesting and informative concurrent programming articles.