Java thread syndrome

xiaoxiao2021-03-06  47

The methods that are often used by programs with multi-threaded capabilities are:

Run (), Start (), Wait (), Notify (), NotifyAll (), Sleep (), Yield (), JOIN ()

There is also an important keyword: synchronized

This article will explain the above content.

One: run () and start ()

Example 1

Public class threadtest extends thread {public void run () {for (int i = 0; i <10; i ) {system.out.print (" i);}}

Public static void main (string [] args) {new threadtest (). start (); new threadtest (). start ();}}

This is a simple multi-threaded program. Run () and start () are two ways that everyone is familiar with. Put the code that hopes parallel processing is in Run (); STAT () is used to automatically call Run (), which is the inherent mechanism of Java. And the access control of the run () must be public, the return value must be Void (this statement is not accurate, the Run () does not return value), and Run () does not have parameters.

These regulations must have already known it, but if you know why the RUN method must declare to this form? This involves the provisions of the Java method overlay and overload. These are important, please read the relevant information.

2: Keywords Synchronized

With SYNCHRONIZED keywords, the running results of the multi-threader program will become controlled. Synchronized keyword is used to protect shared data. Please pay attention to "Sharing Data", you must divide which data is shared data, Java is an object-oriented programming language, so beginners can easily distinguish what data is shared. Please see the example below:

Example 2:

Public Class Threadtest Implements Runnable {

Public synchronized void run () {for (INT i = 0; i <10; i ) {system.out.print (" i);}}

Public static void main (string [] args) {runnable r1 = new threadtest (); runnable r2 = new threadtest (); thread t1 = new thread (r1); thread t2 = new thread (r2); t1.start () ; T2.start ();}}

In this program, Run () is added with the synchronized keyword. Two threads have been created in the MAIN method. You may think that the results of this procedure must be: 0123456789 0123456789. But you are wrong! The Synchronized keyword protected in this program is not shared data (actually in this program, the Synchronized keyword does not play any effect, the results of this program are not pre-determined). T1 and T2 in this program are threads of two objects (R1, R2). Java is an object-oriented programming language. Different objects of different objects are different, R1, R2 has their own Run () methods, and Synchronized makes multiple threads of the same object, only one of them at a moment. Access the SYNCHRONIZED data for this object. Each object has a "lock sign", when a thread of this object accesses a SYNCHRONIZED data for this object, the data of this object will be locked (because "lock sign" is taken by the current thread. Going), only when the current thread accesses the synchronized data it wants to access, the current thread will release "lock sign" so that other threads of the same object have the opportunity to access Synchronized data. Example 3:

Public class threadtest implements runnable {public synchronized void run () {for (int i = 0; i <10; i ) {system.out.print (" i);}}

Public static void main (string [] args) {runnable r = new threadtest (); thread t1 = new thread (r); thread t2 = new thread (r); t1.start ();

T2.Start ();}}

If you run 1000 times this program, its output results must also be each time: 01234567899. Because Synchronized protection here is shared data. T1, T2 is two threads of the same object (R), when one of the threads (e.g., t1) begins to execute the RUN () method, because the Run () is protected by synchronized, the same object, other threads (T2 ) Unable to access the SYNCHRONIZED method (RUN method). Only when T1 is executed after T1 is the opportunity to perform.

Example 4:

Public Class Threadtest Implements Runnable {public void Run () {synchronized (this) {for (int i = 0; i <10; i ) {system.out.print (" i);}}}

Public static void main (string [] args) {runnable r = new threadtest (); thread t1 = new thread (r); thread t2 = new thread (r); t1.start (); t2.start (); } This program is the same as the operation of Example 3. Where possible, the protection range should be minimized, and the example 4 can be used, this represents "this object". There is no need to protect the entire run (), and the code in Run () has only one for loop, so you can only protect the for loop.

Example 5:

Public Class Threadtest IMPLEMENTS RunNable {public void Run () {for (int K = 0; k <5; k ) {system.out.println (thread.currentthread (). getName () ": for loop:" K );

Synchronized (this) {for (int K = 0; k <5; k ) {system.out.println (thread.currentthread (). GetName () ": synchronized for loop:" k);}}}

Public static void main (string [] args) {runnable r = new threadtest (); thread t1 = new thread (r, "t1_name"); thread t2 = new thread (r, "t2_name"); t1.start () ; T2.start ();}}

Run: t1_name: for loop: 1 T1_Name: for loop: 2 T2_Name: for loop: 0 T1_Name: for loop: 3 T2_Name: for loop: 1 T1_Name: for loop: 4 T2_Name: for loop: 2 t1_name: synchronized for loop: 0 t2_name: for loop: 3 t1_name: synchronized for loop: 1 t2_name: for loop: 4 t1_name: synchronized for loop: 2 t1_name: synchronized for loop: 3 t1_name: synchronized for loop: 4 t2_name: Synchronized for loop: 0 t2_name: Synchronized for loop: 1 T2_Name: SYNCHRONIZED for loop: 2 T2_Name: SYNCHRONIZED for loop: 3 T2_Name: SYNCHRONIZED for LOOP: 4

The first for loop is not protected by SYNCHRONIZED. For the first For loop, T1, T2 can be accessed simultaneously. The run results indicate that T1 is executed when T1 is executed, and T2 starts. T1 first implemented the first For loop, and the first FOR cycle has not been executed (T2 is just to K = 2). T1 begins to execute the second for loop. When the second FOR cycle of T1 is executed to k = 1, the first for cycle of T2 is performed. T2 wants to start executing the second For loop, but because T1 first executes the second For loop, the lock flag of this object is naturally in the hand of T1 (the execution of the Synchronized method is in T1), and it is not performed in T1. When the second for cycle, it does not release the lock mark. Therefore, T2 must wait until T1 executes the second for cycle, it can execute the second for loop 3: SLEEP ()

Example 6:

Public class threadtest implements runnable {public void Run () {for (int K = 0; k <5; k ) {if (k == 2) {Try {thread.currentthread (). Sleep (5000);} catch Exception E) {}} system.out.print (" k);}}

Public static void main (string [] args) {runnable r = new threadtest (); thread t = new thread (r); t.start ();}}

The SLEEP method will cause the current thread to suspend execution of a certain period of time (to other thread runs). The reader can run example 6. Look at the results will understand. The SLEEP method will throw an exception and must provide capture code.

Example 7:

Public Class Threadtest Implements Runnable {Public Void Run () {

For (int K = 0; k <5; k ) {if (k == 2) {Try {thread.currentthread (). Sleep (5000);} catch (exception e) {}} system.out.println Thread.currentthread (). Getname () ":" k);}}

Public static void main (string [] args) {runnable r = new threadtest (); thread t1 = new thread (r, "t1_name"); thread t2 = new thread (r, "t2_name"); t1.setpriority (threadPriority .Max_priority); t2.SetPriority; t1.start (); t2.start ();}}

T1 is set to the highest priority, T2 is set to the lowest priority. T1 is not executed, T2 has no opportunity to execute. However, since T1 is in 5 seconds in the middle of the execution, this makes T2 have the opportunity to execute. Readers can try this program. Example 8:

Public Class Threadtest Implements Runnable {Public Synchronized Void Run () {for (INT K = 0; K <5; K ) {IF (k == 2) {Try {thread.currentthread (). Sleep (5000);} catch Exception E) {}

} System.out.println (thread.currentthread (). GetName () ":" k);}}

Public static void main (string [] args) {runnable r = new threadtest (); thread t1 = new thread (r, "t1_name"); thread t2 = new thread (r, "t2_name"); t1.start () ; T2.start ();}}

Readers first run the example 8 program, look at the run results: a thread is in Sleep, and does not release the lock sign of this object.

4: join ()

Example 9:

Public Class Threadtest IMPLEMENTS RunNable {public static int a = 0; public void Run () {for (int K = 0; k <5; k ) {a = a 1;}}

Public static void main (string [] args) {runnable r = new threadtest (); thread t = new thread (r); T.Start (); system.out.println (a);}}

Is the output result of the program? The answer is: it is possible. In fact, when you are hard to encounter output 5, it is usually 5. Not explained here why the output is not 5, I want to say: How can I make the output result is 5! In fact, it is very simple, the Join () method provides this feature. Join () method, it enables the thread that calls the method before it is performed.

The main () method of Example 9 should be as follows:

Public static void main (string [] args) throws exception {runnable r = new threadtest (); thread t = new thread (r); T.Start (); t.join (); system.out.println (a) }

At this time, the output is definitely 5! The Join () method will throw an exception and should provide capture code. Or leave a JDK capture.

Example 10:

Public Class Threadtest IMPLEMENTS RunNable {Public Void Run () {for (int K = 0; k <10; k ) {system.out.print (" k);}} public static void main (String [] args Threws Exception {Runnable R = New ThreadTest (); Thread T1 = New Thread (r); Thread T2 = New Thread (r); T1.Start (); t1.join (); t2.start ();}}

Run this program to see if the result is like example 3

Five: yield ()

The yield () method is similar to the Sleep () method, but it cannot be specified by the user how long it is. According to Sun's statement: The SLEEP method allows the low priority thread to perform opportunities, of course, can also make opportunities to perform with priority and high priority threads. The Yield () method can only make the opportunity to perform with the priority thread.

Example 11:

Public Class Threadtest Implements Runnable {Public Void Run () {8 for (INT K = 0; K <10; K ) {IF (k == 5 && thread.currentthread (). getname (). Equals ("t1") ) {Thread.yield ();} system.out.println (thread.currentthread (). GetName () ":" k);}}

Public static void main (string [] args) {runnable r = new threadtest (); thread t1 = new thread (r, "t1"); thread t2 = new thread (r, "t2"); t1.setpriority (threadPriority .Max_priority); t2.SetPriority; t1.start (); t2.start ();}}

Output: T1: 0 T1: 1 T1: 2 T1: 3 T1: 4 T1: 5 T1: 6 T1: 7 T1: 8 T1: 9 T2: 0 T2: 1 T2: 2 T2: 3 T2: 4 T2: 5 T2: 6 T2: 7 T2: 8 T2: 9

Running this program multiple times, the output is the same. This shows that the yield () method does not have an opportunity to perform different priority threads.

Six: Wait (), notify (), notifyall ()

First, Wait (), Notify (), NotifyAll () These methods are provided by the java.lang.Object class, and the methods told above are provided by the Java.lang.Thread class (the Thread class implements the runnable interface).

Wait (), Notify (), NOTIFYAll () These three methods are used to coordinate multiple threads access to shared data, so these three methods must be used within the Synchronized statement. First look at the example: Example 12:

Public class threadtest IMPLEments Runnable {public static int sharevar = 0; public synchronized void () {=== 0) {for (int i = 0; i <10; i ) {Sharevar ; if (Sharevar == 5 ) {TRY {this.wait (); Catch (Exception E) {}}}} f (shapevar! = 0) {system.out.print (). Getname ()); system.out. Println ("Sharevar =" Sharevar; this.notify ();}}

Public static void main (string [] args) {runnable r = new threadtest (); thread t1 = new thread (r, "t1"); 10 thread t2 = new thread (r, "t2"); t1.start ( ); T2.start ();}}

Run results: T2 Sharevar = 5 T1 Sharevar = 10

The T1 thread is executed first. Due to the initial state, Sharevar is 0, T1 will make Sharevar plus 1, when the value of SharVar is 5, T1 calls the wait () method, T1 will be in a rest state while the lock flag is released. At this time, T2 gets the lock flag to start execution, the value of Sharevar has changed to 5, so T2 directly outputs the value of Sharve, and then calls the notify () method wakes up T1. T1 will then continue to execute before the last rest, add the value of ShaRevar to 10, because the value of Sharevar is not 0, so T1 will output the value of Sharevar at this point, and then call the notify () method, because the moment is already Wait for the thread of the lock flag, so this calling statement does not work.

This program is simple to demonstrate WAIT (), Notify () usage, readers need to continue to explore in practice.

7: About thread supplements

Writing a program with multi-threaded capabilities can inherit the Thread class, or you can implement the runnable interface. How to choose in these two methods? From the object-oriented perspective, the author recommends that you implement the runnable interface. Sometimes you must also implement the runnable interface, such as when you write a small application with multi-threaded power.

Thread scheduling: NewRunningRunnableOtherwise BlockedDeadBlocked in object`sit () poolBlocked in object`slock poolnotify () Schedulercompletesrun () start () sleep () or join () sleep () timeout or thread join () s or interupt () Lockavailablesynchronized () Thread StateSterupt () A Thread object is in a variety of different states in its life cycle, and the image shows this image. Wa in

Calling the start () method makes the thread in the operational state, which means it can be scheduled and executed by the JVM. This doesn't mean that the thread will run immediately.

In fact, multiple threads in the program are not executed simultaneously. Unless the thread is executed on the real multi-CPU computer system, threads must be performed using a single CPU. However, since this happens very quickly, we often think that these threads are executed simultaneously.

The planning scheduler of the Java runtime system is a preemption. If the planning scheduler is running a thread and has another higher priority thread, the currently executing thread is temporarily terminated and the thread of higher priority is performed.

The Java Planning Scheduler will seize the current thread for another thread that has the same priority with the current thread. However, although the planned scheduler itself does not have time slice (ie, it does not give the same priority thread to perform the time slice), the system implementation of the Thread class-based thread may support the time chip allocation. This relies on the specific operating system, Windows and UNIX support on this issue will not be exactly the same.

Since you can't affirm that the applet will run on what operating system, you should not write a program that relies on the timefall assignment. That is to say, you should use the Yield method to allow threads that allow the same priority to perform, rather than wanting to automatically get a CPU time slice every thread.

The THREAD class provides the mechanism for processing threads that are not related to the system. However, the actual implementation of threads depends on the operating system where Java runs. Therefore, the threaded program does use the operating system that supports the thread.

When you create a thread, you can give it a priority. The higher the priority, the more you can affect the running system. The Java Running System uses a planning scheduler responsible for running all existed in all executing Java programs. The plan scheduler actually uses a fixed priority algorithm to ensure that the highest priority thread in each program gets the CPU - allowing the highest priority thread to execute before other threads.

For situations where there are several threads in one program waiting to be performed, the planning scheduler selection them, when performing the next choice, select the thread that did not perform in front, all threads with the same priority are subject to Equality treatment. The lower priority thread can be executed after the thread of higher priority is dead or after entering the incomplete state.

Continue to discuss WAIT (), Notify (), NotifyAll ():

When the thread performs WAIT () call to a particular object, that thread is placed in the waiting pool associated with that object. In addition, call the Wait () thread automatically releases the lock sign of the object.

You can call different Wait (): wait () or wait (long timeout)

When performing a NOTIFY () call to a particular object, an arbitrary thread is removed from the object's waiting pool, and placed in the lock laser waiting in the pool, where the thread is always waiting until the lock mark of the object can be obtained. The NotifyAll () method will remove all threads waiting for That object from the object waiting in the pool and put it in the lock mark waiting in the pool. Only the lock flag is waiting for the thread in the pool to get the lock mark of the object, the lock mark allows the thread to continue running from the last place interrupted by Wait ().

In many systems that implement the wait () / notify () mechanism, the wake up thread must be the longest wait for the longest thread. However, in Java technology, this is not guaranteed.

Note that notify () can be called regardless of whether there is a thread waiting. If a notify () method is called for an object, while the lock mark of this object is waiting for the pool without thread, then notify () calls will not work.

In Java, multithreading is a magical topic. The reason why it is "magical" because the results of multi-threaded procedures are not predictable, but we can control the execution of multi-threaded programs through some ways. To use multithreading, readers need a lot of practices.

In addition, starting from JDK 1.2, Sun does not recommend using resume (), stop (), suspend ()

转载请注明原文地址:https://www.9cbs.com/read-117650.html

New Post(0)