From the school to A factory all the way sunshine vicissitudes of life

Please go to www.codercc.com


1. Control concurrent access to resources –Semaphore

Semaphore can be understood as a Semaphore, which controls the number of threads that can access a resource concurrently to ensure that multiple threads can properly use a particular resource. Semaphore is a license that a thread needs to acquire before it can proceed. Otherwise, it must wait until the Semaphore method blocks. When the business function is finished, the license needs to be returned through the release() method so that other threads can get the license to continue.

Semaphore can be used for flow control, especially when common resources are limited, such as database connections. If multiple threads read data and need to store the data in the database, and the maximum number of available database connections is 10, you need to use Semaphore to limit the number of threads that can concurrently access the database connection resource to 10. Semaphore is particularly appropriate in applications where resource usage is limited.

Here are Semaphore’s main methods:

Void acquire() throws InterruptedException Void acquire(int permits) throws InterruptedException void release() // Release a specified number of permits void Release (int permits) // Attempt to obtain permits, true immediately if successful, otherwise false Boolean tryAcquire() // same as tryAcquire, Boolean tryAcquire(int permits) // Return true if a license can be obtained immediately or within a specified time. Otherwise return false Boolean tryAcquire(long timeout, TimeUnit Unit) throws InterruptedException // Same as the previous method, except that multiple permissions are obtained hereCopy the code

boolean tryAcquire(int permits, long timeout, TimeUnit unit)

Int availablePermits() // Returns the number of threads waiting for permits int getQueueLength() // Whether any threads are waiting for permits Boolean hasQueuedThreads() Collection<Thread> getQueuedThreads()Copy the code

In addition, the Semaphore constructor supports specifying that it is fair and that it is not fair by default to ensure throughput.

A case in point

Here is a simple example to illustrate the use of Semaphore. Let’s simulate a scenario like this. One day, the class teacher needed 10 students to come to the desk to fill out a form, but the teacher only prepared 5 pens, therefore, can only ensure that only 5 students can get pens and fill in the form, the students who did not get pens can only wait until the front of the students used up, to get pens to fill in the form. The sample code is as follows:

public class SemaphoreDemo {
Private static Semaphore Semaphore = new Semaphore(5); Public static void main (String [] args) {/ / said 50 students ExecutorService service = Executors. NewFixedThreadPool (10); for (int i = 0; i &lt; 10; i++) { service.execute(() -&gt; {try {system.out.println (thread.currentThread ().getName() + "......" ); semaphore.acquire(); System.out.println(thread.currentThread ().getName()); System.out.println(thread.currentThread ().getName() + "Fill in the form ing....." ); TimeUnit.SECONDS.sleep(3); semaphore.release(); System.out.println(thread.currentThread ().getName() +" ); } catch (InterruptedException e) { e.printStackTrace(); }}); } service.shutdown(); }Copy the code

} Output:

Pool-1-thread-1 students are ready to obtain pen...... Pool-1-thread-1 fill in the form ing..... Pool-1-thread-2: Get pen...... Pool-1-thread-2 Fill in the form ing..... Pool-1-thread-3: Get pen...... Pool-1-thread-4: Get pen...... Pool-1-thread-3 pool-1-thread-4 Pool-1-thread-4 Fill in the form ing..... Pool-1-thread-3 Fill in the form ing..... Pool-1-thread-5 Get pen...... Pool-1-thread-5 fill in the form ing.....

Pool-1-thread-6 Students are ready to obtain pen...... Pool-1-thread-7 get pen...... Pool-1-thread-8 students are ready to get pen...... Pool-1-thread-9 students are ready to get pen...... Pool-1-thread-10 get pen......

Copy the code

Pool-1-thread-4 filled out the form and returned the pen !!!!!! Pool-1-thread-9 Fill in the form ing..... Pool-1-thread-5 filled out the form and returned the pen !!!!!! Pool-1-thread-7 Fill in the form ing..... Pool-1-thread-8 Fill in the form ing..... Pool-1-thread-1 filled out the form and returned the pen !!!!!! Pool-1-thread6 Fill in the form ing..... Pool-1-thread-3 filled out the form and returned the pen !!!!!! Pool-1-thread-2 filled out the form and returned the pen !!!!!! Pool-1-thread-10 Fill in the form ing..... Pool-1-thread-7 filled out the form and returned the pen !!!!!! Pool-1-thread-9 filled out the form and returned the pen !!!!!! Pool-1-thread-8 filled out the form and returned the pen !!!!!! Pool-1-thread-6 filled out the form and returned the pen !!!!!! Pool-1-thread-10 filled out the form and returned the pen !!!!!!

According to the analysis of the output result, the maximum number of permits allowed by Semaphore is 5, that is, the maximum number of concurrent execution threads is 5. It can be seen that the first five threads (the first five students) get the pen first and fill in the form, while the other five threads (6-10) can only block and wait because they cannot obtain the permission. When the thread pool-1-thread-4 releases the permit, pool-1-thread-9 obtains the permit and continues. The same is true for other threads. As you can see from this example, Semaphore is suitable for concurrent access control of specific resources. If a business scenario requires traffic control, Semaphore should be preferred.

2. Data exchange tool between threads – Sano11003

Sano1100is a tool class used for interthread collaboration, which is used to exchange between two threads. It provides a synchronization point of exchange at which two threads can exchange data. If one thread executes the Exchange method first, it synchronously waits for the other thread to execute the Exchange method. At this point, both threads have reached the synchronization point and the two threads can exchange data.

Apart from a non-parametric construction method, the main method is also simple:

// When one thread executes the method, it waits for the other thread to execute the method, so both threads reach the synchronization point. V exchange(V x) throws InterruptedException // Added timeout period V Exchange (V x, Long timeout, TimeUnit Unit) throws InterruptedException, TimeoutExceptionCopy the code

A case in point

It is easy to understand, and a simple example is used for its specific use. Let’s simulate such a scene, in the youth filled with middle school times, during the class, boys often give corridor for their favorite girl to send love letters, I believe we have done such a thing :). The boys would go to the door of the girl’s classroom, and then they would wait for the girl to come out, and there would be a synchronization point, and then they would exchange tokens, so they would exchange data. Now, let’s simulate the situation.

public class ExchangerDemo {
    private static Exchanger<String> exchanger = new Exchanger();
Public static void main (String [] args) {/ / is for boys and girls ExecutorService service = Executors. NewFixedThreadPool (2); service.execute(() -&gt; {// 1100. exchange(" I've actually had a crush on you for a long time......" ); System.out. Println (" girl says: "+ girl); } catch (InterruptedException e) { e.printStackTrace(); }}); service.execute(() -&gt; {try {system.out. println(" girl slowly from the classroom you walk out......" ); TimeUnit.SECONDS.sleep(3); // 1100. exchange(' I like you too...... ') ); System.out. Println (" boy say: "+ boy); } catch (InterruptedException e) { e.printStackTrace(); }}); }Copy the code

}

Output result:

Copy the code

Girls slowly from the classroom you come out...... The boy said: I actually have a crush on you for a long time...... The girl say: I also like you......

This example is very simple and illustrates the basic use of SANo11003. When both threads reach the synchronization point where the Exchange method is called, the two threads can exchange data with each other.