Inter-thread communication

Source: Internet
Author: User

    1. Notification wait mode
The waiting party follows the following guidelines. 1) Gets the lock of the object. 2) If the condition is not satisfied, then the wait () method of the calling object is notified and the condition is still checked. 3) The corresponding logic is executed when the condition is satisfied. The corresponding pseudo-code is as follows. Synchronized (object) {while (condition not satisfied) {object. Wait ();} Corresponding processing logic} The notifying party follows the following guidelines. 1) Gets the lock of the object. 2) Change the conditions. 3) Notifies all threads waiting on the object. The corresponding pseudo-code is as follows. Synchronized (object) {Change the Condition object. Notifyall ();}
    1. Pipeline
The difference between a pipe input/output stream and a normal file input/output stream or a network input/output stream is that it is primarily used for data transfer between threads, while the medium being transmitted is memory. The pipeline input/output stream consists of the following 4 specific implementations: PipedOutputStream, PipedInputStream, Pipedreader, and PipedWriter, the first two oriented bytes, and the latter two oriented characters. For a stream of type piped, you must first bind, that is, call the Connect () method, and if you do not bind the input/output stream, access to the stream will throw an exception.
    1. ThreadLocal
Threadlocal is how to create a copy of a variable for each thread:        First, Within each thread, there is a member variable threadlocals of type Threadlocal.threadlocalmap, which is used to store the actual copy of the variable, the key value is the current threadlocal variable, and value is a copy of the variable ( Variable of type T).         Initially, in thread, Threadlocals is empty, when the Get () method or set () method is called through the threadlocal variable, The threadlocals in the thread class is initialized, and the current threadlocal variable is the key value, threadlocal the copy variable to save to value, and to Threadlocals.         Then in the current thread, if you want to use a copy variable, you can find it in threadlocals by using the Get method.         summarize:        1) The actual copy created by threadlocal is stored in the threadlocals of each thread's own;  & nbsp     2) Why the Threadlocals type Threadlocalmap has a key value of threadlocal object, because there can be more than one threadlocal variable in each thread, As in the code above, longlocal and stringlocal;        3) must be set before a get is made, otherwise a null pointer exception will be reported;        You must override the InitialValue () method if you want to have normal access without calling set before get. I. Understanding of ThreadLocal ThreadLocal, many places are called thread-local variables, and some places are called thread-local storage, in fact, the meaning is similar.  Maybe a lot of friends know that threadlocal a replica is created for a variable in each thread, each thread can access its own internal copy variable.  This sentence literally seems easy to understand, but the real understanding is not so easy. Let's look at an example first:
classConnectionManager {Private StaticConnection connect =NULL;  Public StaticConnection OpenConnection () {if(Connect = =NULL) {Connect=drivermanager.getconnection (); }        returnConnect; }          Public Static voidCloseConnection () {if(connect!=NULL) Connect.close (); }}


Suppose there is a database link management class that has no problem using this code in a single thread, but what if it is used in multi-threading? Obviously, there is a thread-safety problem with Multithreading: First, there are 2 methods that are not synchronized, and it is likely that connect is created multiple times in the OpenConnection method, and second, because connect is a shared variable,  It is necessary to use synchronization to ensure thread safety when calling connect, because it is likely that one thread is using Connect for database operations, while another thread calls CloseConnection to close the link.  Therefore, for thread-safety reasons, the two methods of this code must be synchronized, and synchronous processing is required where connect is called.  This will greatly affect the efficiency of the execution of the program, because when a thread uses connect for database operations, the other threads only wait. So let's take a closer look at this question, does this place need to be shared with the connect variable? In fact, it is not necessary.  If there is a connect variable in each thread, access to the connect variable between the threads is actually not dependent, i.e. one thread does not need to be concerned about whether the other thread has modified the connect. Here, a friend may think that since you do not need to share this variable between threads, you can do this directly, create a database link in each method that needs to use the database connection, and then release the connection after the method call is complete. such as the following:
classConnectionManager {PrivateConnection connect =NULL;  PublicConnection OpenConnection () {if(Connect = =NULL) {Connect=drivermanager.getconnection (); }        returnConnect; }          Public voidCloseConnection () {if(connect!=NULL) Connect.close (); }}  classdao{ Public voidInsert () {ConnectionManager ConnectionManager=NewConnectionManager (); Connection Connection=connectionmanager.openconnection (); //use connection to operateconnectionmanager.closeconnection (); }}

There is really no problem with this processing, because each time a connection is created inside a method, there is no thread-safety problem between threads. However, this can have a fatal impact: causing the server to be very stressful and severely impacting program execution performance.  Because the database connection needs to be opened and closed frequently in the method, this can not seriously affect the efficiency of the program execution, but also may cause the server pressure is huge. It would be fitting to use threadlocal in this case, because threadlocal creates a copy of the variable in each thread, that is, there is a variable inside each thread that can be used anywhere inside the thread, and the threads do not affect each other.  As a result, there is no thread-safety issue, and there is no serious impact on program execution performance. Note, however, that although threadlocal is able to solve the above problem, due to the creation of replicas in each thread, it is important to consider the consumption of resources, such as memory usage, which is larger than threadlocal.  Two. In-depth analysis of the Threadlocal class in the above talk about the threadlocal of some understanding, then we look at how the specific threadlocal is implemented. Let's look at some of the methods provided by the Threadlocal class:
 Public T get () {}  Public void set (T value) {}  Public void remove () {} protected T InitialValue () {}

The Get () method is used to get a copy of the variable that threadlocal holds in the current thread, set () to make a copy of the variable in the current thread, and remove () to remove the copy of the variable in the current thread, InitialValue () is a protected method,  It is generally used for rewriting when used, and it is a lazy loading method, which is described in detail below.  First, let's take a look at how the Threadlocal class creates a copy of a variable for each thread. First look at the implementation of the Get method:

The first sentence is to obtain the current thread, and then get to a map,map type of Threadlocalmap by Getmap (t) method.  Then get to the <key,value> key-value pair, and note that this is what gets the key-value pair, not the current thread T.  If successful, the value is returned.  If map is empty, call the Setinitialvalue method to return value. Each of our above sentences is carefully analyzed: First look at what the Getmap method does:

What might not have occurred to you is that in Getmap, it is called the current thread T, which returns a member variable threadlocals in the present thread T. So let's go ahead and take a look at the member variable threadlocals in the thread class:

is actually a threadlocalmap, this type is an inner class of the Threadlocal class, and we continue to take a look at the implementation of Threadlocalmap:

You can see that the entry of Threadlocalmap inherits WeakReference and uses threadlocal as the key value. Then go on to see the concrete implementation of the Setinitialvalue method:

It is easy to understand, that is, if the map is not empty, set the key value pairs, empty, and then create a map, look at the implementation of Createmap:

At this point, perhaps most friends already understand how threadlocal creates a copy of a variable for each thread: first, Within each thread, there is a member variable threadlocals of type Threadlocal.threadlocalmap, which is used to store the actual copy of the variable, the key value is the current threadlocal variable, and value is a copy of the variable (  Variable of type T). Initially, in thread, Threadlocals is empty, and when the Get () method or set () method is called through the threadlocal variable, the threadlocals in the thread class is initialized.  And with the current threadlocal variable as the key value, to threadlocal the copy variable to save as value, save to Threadlocals.  Then in the current thread, if you want to use a copy variable, you can find it in the threadlocals by using the Get method. Here's an example of how the threadlocal can achieve the effect of creating a copy of a variable in each thread:
 Public classTest {ThreadLocal<Long> longlocal =NewThreadlocal<long>(); ThreadLocal<String> stringlocal =NewThreadlocal<string>();  Public voidset () {Longlocal.set (Thread.CurrentThread (). GetId ());    Stringlocal.set (Thread.CurrentThread (). GetName ()); }          Public LongGetlong () {returnLonglocal.get (); }          PublicString getString () {returnStringlocal.get (); }          Public Static voidMain (string[] args)throwsinterruptedexception {FinalTest test =NewTest ();        Test.set ();        System.out.println (Test.getlong ());                      System.out.println (Test.getstring ()); Thread Thread1=NewThread () { Public voidrun () {test.set ();                System.out.println (Test.getlong ());            System.out.println (Test.getstring ());        };        };        Thread1.start ();                 Thread1.join ();        System.out.println (Test.getlong ());    System.out.println (Test.getstring ()); }}

The output of this code is:

From the output of this code, it can be seen that in the main thread and the THREAD1 thread, the longlocal saved copy values and Stringlocal saved copy values are not the same.  The last time the copy value is printed again on the main thread is to prove that the replica values in the main thread and the THREAD1 thread are indeed different. To summarize: 1) The actual copy created through threadlocal is stored in each thread's own threadlocals, 2) Why the Threadlocals type Threadlocalmap The key value is the Threadlocal object, Because there can be more than one threadlocal variable in each thread, like longlocal and stringlocal in the code above, 3) must be set before a get is made, otherwise the null pointer exception will be reported, and if you want to have normal access without calling set before get,    You must override the InitialValue () method. Because in the above code analysis process, we found that if there is no first set, that is, the map can not find the corresponding storage, then by calling the Setinitialvalue method to return I, and in the Setinitialvalue method, there is a statement is t value = InitialValue (), and by default, the InitialValue method returns NULL.

Look at the following example:
 Public classTest {ThreadLocal<Long> longlocal =NewThreadlocal<long>(); ThreadLocal<String> stringlocal =NewThreadlocal<string>();  Public voidset () {Longlocal.set (Thread.CurrentThread (). GetId ());    Stringlocal.set (Thread.CurrentThread (). GetName ()); }          Public LongGetlong () {returnLonglocal.get (); }          PublicString getString () {returnStringlocal.get (); }          Public Static voidMain (string[] args)throwsinterruptedexception {FinalTest test =NewTest ();        System.out.println (Test.getlong ());         System.out.println (Test.getstring ()); Thread Thread1=NewThread () { Public voidrun () {test.set ();                System.out.println (Test.getlong ());            System.out.println (Test.getstring ());        };        };        Thread1.start ();                 Thread1.join ();        System.out.println (Test.getlong ());    System.out.println (Test.getstring ()); }}

In the main thread, the runtime will report a null pointer exception without first set and direct get. However, if you change to the following code, the InitialValue method is overridden:
 Public classTest {ThreadLocal<Long> longlocal =NewThreadlocal<long>(){        protectedLong InitialValue () {returnThread.CurrentThread (). GetId ();    };    }; ThreadLocal<String> stringlocal =NewThreadlocal<string>(){; protectedString InitialValue () {returnThread.CurrentThread (). GetName ();    };          };  Public voidset () {Longlocal.set (Thread.CurrentThread (). GetId ());    Stringlocal.set (Thread.CurrentThread (). GetName ()); }          Public LongGetlong () {returnLonglocal.get (); }          PublicString getString () {returnStringlocal.get (); }          Public Static voidMain (string[] args)throwsinterruptedexception {FinalTest test =NewTest ();        Test.set ();        System.out.println (Test.getlong ());                      System.out.println (Test.getstring ()); Thread Thread1=NewThread () { Public voidrun () {test.set ();                System.out.println (Test.getlong ());            System.out.println (Test.getstring ());        };        };        Thread1.start ();                 Thread1.join ();        System.out.println (Test.getlong ());    System.out.println (Test.getstring ()); }}

You can call get directly without first set.  Three. The most common threadlocal usage scenarios for threadlocal applications are the use of database connections, session management, and so on. For example: The following code is excerpted from:
     Importjava.sql.Connection; ImportJava.sql.DriverManager; Importjava.sql.SQLException;  Public classConnectionManager {Private StaticThreadlocal<connection> Connectionholder =NewThreadlocal<connection>() {@OverrideprotectedConnection InitialValue () {Connection conn=NULL; Try{conn=Drivermanager.getconnection ("Jdbc:mysql://localhost:3306/test", "username",                               "Password"); } Catch(SQLException e) {e.printstacktrace (); }                   returnConn;                  }           };  Public StaticConnection getconnection () {returnConnectionholder.get (); }                   Public Static voidSetConnection (Connection conn) {Connectionholder.set (conn); }       }  

Inter-thread communication

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.