Java Thread should pay attention to problems
WANG Hailong
Java's thread programming is very simple. But sometimes you will see some error usage of threads. Some questions should be noted below.
1. Constantity of synchronous objects
All Java Objects Are References.
For local variables and parameters, the basic data types such as int, float, double, boolean in Java are on the stack. These basic types are unable to synchronize; objects in Java (root objects are Object), all in the stack, point to the object's Reference in the stack.
The synchronization object in Java is actually synchronized with the "object address" referred to in ReferenceE. The problem that needs to be aware of is that don't re-value the synchronization object. for example. Class A Implements Runnable {Object Lock = New Object (); Void Run () {{Synchronized (LOCK) {// Do Something ... Lock = New Object ();}}}}}}} Run function This synchronization code is actually meaningless. Because every Lock is reassigned by Reference, each thread is synchronized in the new Reference. Everyone may feel strange, how can you raise such an example. Because I have seen such a code, the synchronization object is resented in other functions. This problem is difficult to find. So, the synchronization object should generally be declared as femance.final object lock = new object ();
It is also a good choice to use Singleton Pattern design mode to get synchronous objects.
2. How to place shared data
There are two ways to achieve threads, one is to inherit the Thread class, one is to implement the Runnable interface.
Examples of the above, using methods for implementing the runnable interface. This paper recommends this method.
First, put the data you need to share in a class that implements the Runnable interface, then pass this class to the constructor of multiple Thread. In this way, the newly created multiple Threads all have a RunNable instance to share the same data.
If you use the method of inheriting the Thread class, you have to use Static static members. If the shared data is more, a large number of Static static members are needed, and the program data structure is confusing, it is difficult to expand. This should be avoided as much as possible.
Write a multi-thread code to handle a slightly complex point problem. The advantages and disadvantages of the two methods are known.
3. Synchronize particle size
The smaller the particle size of thread synchronization, that is, the smaller the code block of the thread synchronization is, the smaller the better. Try to avoid declaring methods with synchronized modifiers. Try to use Synchronized (anObject), if you don't want to introduce new synchronization objects, use Synchronized (this). Moreover, the smaller the SYNCHRONIZED code block.
4. Notification between threads
Here is the word "notification" instead of "communication", it is to avoid the magnification of the meaning.
Notification between threads is implemented by WAIT () and Notify () or NotifyAll () methods of the Object object.
Here is an example to show its working principle:
Suppose there are two threads, a and b. A synchronization object, Lock.
1. First, the thread a obtains the Lock synchronization object via synchronized (LOCK), then call the Lock.Wait () function, discard the Lock synchronization object, thread a stop running, and enter the waiting queue. 2. Thread B obtains the Lock synchronization object of thread a abandoned LOCK synchronization with Synchronized (LOCK), and then calls Lock.Notify () or Lock.NotifyAll () notifies the thread A inside the queue.
3. Thread a From the waiting queue, enter the Ready queue, wait for the schedule.
4. Thread B continues to process, after the Synchronized (LOCK) block, abandon the Lock synchronization object.
5. Thread A gets a LOCK synchronization object and continues to run.
The example code is as follows:
Public Class SharedResource IMPLEments Runnable {
Object lock = new object ();
Public void run () {
// Get the name of the current thread.
String threadname = thread.currentthread (). Getname ();
IF ("a" .Equals (threadname)) {
Synchronized (LOCK) {// Thread A Get the Lock Synchronization Object by Synchronized (LOCK)
Try {
System.out.println ("A Gives Up Lock.");
Lock.wait (); // Call the loc.wait () function, abandon the Lock synchronization object,
// Thread A stops running, enter the waiting queue.
} catch (interruptedexception e) {
}
// Thread A After re-acquiring the Lock synchronization object, continue to run.
System.out.println ("a got lock again and amount t.");
} // end of synchronized (lock)
}
IF ("b" .Equals (threadname)) {
Synchronized (LOCK) {// Thread B Gets the Lock synchronization object abandoned by Synchronized (LOCK)
System.out.println ("B Got Lock.");
Lock.notify (); // Notify the thread A in the queue, enter the Ready queue, wait for the schedule.
// Thread B continues to process, after the Synchronized (LOCK) block, discard the Lock synchronization object.
System.out.println ("B Gives Up Lock.");
} // end of synchronized (lock)
Boolean Haslock = Thread.Holdslock (LOCK); // Check if B has a LOCK synchronization object.
System.out.println ("b Has Lock? -" HASLOCK); // False.
}
}
}
Public class testmain {
Public static void main () {
Runnable resource = new sharedResource ();
Thread a = new thread (resource, "a");
A.Start ();
/ / Forced the main thread to stop running so that the thread A starts running.
Try {
Thread.sleep (500);
} catch (interruptedexception e) {
}
Thread B = New Thread (Resource, "B"); B.Start ();
}
}
5. Cross-class synchronization object
For simple questions, you can put the synchronous code of the access shared resource in one class.
But for complex issues, we need to divide the problem into several parts, requiring several different classes to handle problems. At this time, you need to share synchronization objects in different classes. For example, sharing synchronous objects between producers and consumers, sharing synchronization objects between readers and writers.
How to share synchronization objects in different classes. There are several ways to achieve,
(1) The method mentioned earlier, using Static static members, (or use Singleton Pattern.)
(2) Pass the method of passing the synchronization object to a different class.
(3) Use "atomicity" that utilizes string constants.
For the third method, let me explain it. In general, the string constants in the program code have uniqueness, i.e., there is no two copies of the same string constance in memory.
(Normally, after C , C language program is compiled, it also has the same characteristics.)
For example, we have the following code.
String a = "atom";
String b = "atom";
We have a reason to say that A and B points to the same string. That is, a == b.
Note that the code for declaring the string variable does not meet the above rules.
String C = New String ("atom");
String D = New String ("atom");
The declaration of C and D here is a declaration of a string variable, so C! = D.
With the above understanding, we can use string constants as synchronous objects.
For example, we use Synchronized ("MyLock", "MyLock"), "MyLock" .Wait (), "MyLock" .Notify (), thread synchronization between different classes.
This article is not strongly recommended, but it is illustrated that there is such a method.
This article recommends the second method, (2) the method of passing the synchronization object to different classes with parameter transmission.