Java concurrent Programming (iv) Common synchronization tool classes

Source: Internet
Author: User

The synchronization tool class can make any kind of object, as long as the object can coordinate the control flow of the control thread according to its own state. The blocking queue can be used as a synchronization tool class, and other types of synchronization tool classes include: semaphore (Semaphore), fence (Barrier), and latching (Latch).


Atresia

First, let's introduce the latching.

Latching acts as a door: the door is closed until the latch reaches a certain state, and all threads wait at the door (block). Only when the door is opened, will all threads continue to run at the same time.

Latching can be used to ensure that certain activities do not continue until other activities have been completed, such as:

1. Ensure that a calculation continues after all of its resources have been initialized. Binary latching (only two states) can be used to indicate that "resource R has been initialized", and all required R operations must first wait on this lockout.

2. Ensure that a service is started after all other services have been started. Multiple latching is required. Let s wait on each latch until all the latches are open before they continue to run.

3. Wait until a participant in an operation (for example, a player in a multi-player game) is ready to continue execution. In this case, when all players are ready, the lockout will reach the end state.

The Countdownlatch is a flexible latching implementation that can be used in all of the above scenarios. The latching state contains a counter that is initialized to a positive number, indicating how many events to wait for. The countdown () method decrements the counter, indicating that a piece occurred in the waiting event. The await () method blocks until the counter value changes to 0.

Below, we use latching to implement the ability to calculate the run time of multiple child threads in the main thread. The logic is to use two latching, the "Start gate" is used to control the child threads running concurrently, "End gate" to identify whether the child thread is complete.

Package Org.bupt.xiaoye;import Java.util.concurrent.countdownlatch;public class Test {public static int nthread = 5; public static void Main (string[] args) throws interruptedexception{final countdownlatch startgate = new Countdownlatch (1) Final Countdownlatch endgate = new Countdownlatch (nthread); for (int i =0;i<nthread;i++) {new Thread () {@ overridepublic void Run () {try{startgate.await (); Thread.Sleep (300);} catch (Interruptedexception e) {}finally{system.out.println (Thread.CurrentThread (). GetName () + "ended"); Endgate.countdown ();}}}. Start ();} Long start = System.nanotime (); Startgate.countdown (); endgate.await (); Long end = System.nanotime (); SYSTEM.OUT.PRINTLN ("Total Time:" + (End-start));}}

Futuretask

Futuretask can also be used as latching. It represents an abstract calculation of the generated results. is implemented by callable, which is equivalent to a Runnable that produces results, and can be in the following three states: Waiting, running, running. When the Futuretask enters the completed state, it will remain in this state.

The future.get is used to obtain the results of the calculation and is blocked if the futuretask is not yet complete. Futuretask passes the calculated result from the thread that performs the calculation to the thread that gets the result, and the Futuretask specification ensures that the delivery process can achieve a secure release of the results.

Futuretask represents asynchronous tasks in the executor framework and can also be used to represent some long-time calculations that can be started before the calculation results are used.

Let's construct a simple asynchronous task to simply demonstrate how futuretask is used.

Package Org.bupt.xiaoye;import Java.util.concurrent.callable;import java.util.concurrent.ExecutionException; Import Java.util.concurrent.futuretask;public class Preloader {private final futuretask<integer> future = new Futuretask<integer> (New callable<integer> () {public Integer call () throws Exception {Thread.Sleep (3000); return 969;}}); Private final thread thread = new Thread (future);p ublic void Start () {Thread.Start ();} Public Integer get () throws Exception {Try{return future.get ();} catch (Executionexception e) {throwable cause = E.getcause (); throw launderthrowable (Cause);}} private static Exception launderthrowable (Throwable cause) {if (cause instanceof RuntimeException) return ( RuntimeException) Cause;else if (cause instanceof Error) throw (error) Cause;else throw new IllegalStateException ("Not Che Cked ", cause);} public static void Main (string[] args) throws Exception{preloader p = new Preloader ();p. Start (); Long start = System.curren Ttimemillis (); System.out.println (P.get ());System.out.println (System.currenttimemillis ()-start);}} 

Signal Volume

The previously spoken lockout controls the time of access, while the semaphore is used to control the number of operations that access a particular resource and control the space. And the latch can only be reduced, one-time use, while the semaphore request can be released, can be increased and reduced. The count semaphore can also be used to implement a resource pool, or to impose boundaries on the container.

Semaphone manages this set of licenses (permit), which can be specified by constructors. A blocking method, acquire, is also provided to obtain the license. The release method is also provided to express the release of a license.

Semaphone can turn any container into a bounded blocking container, such as for implementing a resource pool. For example, a database connection pool. We can construct a fixed-length connection pool, using the blocking method acquire and release to get the release connection instead of failing to get it. (Of course, it's easier to use Blockingqueue to save the connection pool's resources at the beginning of the design process.)

For example, we change a normal set container to a block bounded.

Package Org.bupt.xiaoye;import Java.util.collections;import Java.util.hashset;import java.util.set;import Java.util.concurrent.semaphore;public class Boundedhashset<t> {private final set<t> set;private Semaphore Sem;public boundedhashset (int bound) {if (bound < 1) throw new IllegalStateException (); set = Collections.synchronizedset (New hashset<t> ()); sem = new Semaphore (bound);} Public boolean Add (T e) throws interruptedexception {Sem.acquire (); Boolean wasadded = false;try {wasadded = Set.add (e); ret Urn wasadded;} finally {if (!wasadded) sem.release ();}} public boolean remove (T e) {Boolean wasremoved = Set.remove (e); if (wasremoved) sem.release (); return wasremoved;}}


Fence

Fences (bariier) are similar to latching, which can block a group of threads from knowing that an event occurs. The key difference between fencing and latching is that all threads must reach the fence position at the same time to continue execution. Latching is used to wait for the waiting time while the fence is used to wait for the thread.

Cyclicbarrier can enable a number of parties to converge in a fence position over and over again, which is useful in parallel iterative algorithms: splitting a problem into a series of independent sub-problems. When the thread reaches the fence position, call the await () method, which is the blocking method until all the threads reach the fence position, then the fence is opened and all the threads are freed, and the fence is reset for the next use.

Another form of fence is exchanger, which is a two-party (two-party) fence in which the parties exchange data on the fence position. For example, when one thread wants to write data to a buffer, another thread reads the data from the buffer. These threads can use Exchanger to converge and swap the slow buffer with the empty buffer. When two threads swap objects through Exchanger, the interchange securely publishes the two objects to the other.

Exchanger may be considered a bidirectional form of synchronousqueue. We can also use two synchronousqueue to realize the function of exchanger.

Class Fillandempty {exchanger<databuffer> Exchanger = new exchanger<databuffer> (); DataBuffer Initialemptybuffer = ... a made-up type databuffer Initialfullbuffer = ... class Fillingloop implements Run       nable {public void run () {DataBuffer currentbuffer = Initialemptybuffer;           try {while (Currentbuffer! = null) {Addtobuffer (currentbuffer);         if (Currentbuffer.isfull ()) Currentbuffer = Exchanger.exchange (Currentbuffer);     }} catch (Interruptedexception ex) {...} handle ...} }} class Emptyingloop implements Runnable {public void run () {DataBuffer Currentbuffer = Initialfullbuffe       R           try {while (Currentbuffer! = null) {Takefrombuffer (currentbuffer);         if (Currentbuffer.isempty ()) Currentbuffer = Exchanger.exchange (Currentbuffer);     }} catch (Interruptedexception ex) {...} handle ...} }} void Start () {New Thread(New Fillingloop ()). Start ();   New Thread (New Emptyingloop ()). Start (); }  }




Java concurrent Programming (iv) Common synchronization tool classes

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.