In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the relevant knowledge of "what are the basic operations of java highly concurrent threads". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
Create a new thread
Creating a new thread is easy. You just need to create a thread object using the new keyword and then call its start () to start the thread.
Thread thread1 = new Thread1 (); t1.start ()
So what does the thread start () do? The thread has a run () method, and start () creates a new thread and has it execute the run () method.
It should be noted here that the following code can also be compiled and executed normally. However, instead of creating a new thread, the run () method is called in the current thread, and the run method is simply called as a normal method.
Thread thread1 = new Thread1 (); thread1.run ()
So, I hope you will notice the difference between calling the start method and calling the run method directly.
The start method starts a thread, and the run method only executes the code in the run method serially in the current thread.
By default, the thread's run method has nothing, and it ends immediately after starting a thread, so if you need a thread to do something, you need to write your code into the run method, so you must rewrite the run method.
Thread thread1 = new Thread () {@ Override public void run () {System.out.println ("hello, I am a thread!");}}; thread1.start ()
The above is implemented using anonymous inner classes, overrides the run method of Thread, and prints a message. We can customize a thread by inheriting the Thread class and then overriding the run method. But considering that java is single inheritance, in terms of extensibility, it is better for us to implement an interface to customize a thread. Java happens to provide a Runnable interface to customize a thread.
@ FunctionalInterface public interface Runnable {public abstract void run ();}
The Thread class has a very important constructor:
Public Thread (Runnable target)
Let's take a look at Thread's run method:
Public void run () {if (target! = null) {target.run ();}}
When we start the thread's start method, the thread executes the run method, and the run method calls the target's run method passed in by the Thread constructor method.
Implementing the Runnable interface is a common and recommended practice.
Terminating thread
Generally speaking, the thread ends when it is finished, and there is no need to shut it down manually. But what can we do if we want to shut down a running thread? You can take a look at the stop () method provided in the Thread class. Calling this method, you can immediately terminate a thread, which is very convenient.
Package com.itsoku.chat01; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.TimeUnit; / * description:
* time:2019/7/12 17:18
* author: Wechat official account: passer-by Java, specializing in java technology sharing (taking you to play with crawlers, distributed transactions, asynchronous messaging services, task scheduling, sub-database tables, big data, etc.), please follow! * / @ Slf4j public class Demo01 {public static void main (String [] args) throws InterruptedException {Thread thread1 = new Thread () {@ Override public void run () {log.info ("start"); boolean flag = true While (flag) {;} log.info ("end");}}; thread1.setName ("thread1"); thread1.start () / / current thread hibernates for 1 second TimeUnit.SECONDS.sleep (1); / / closes thread thread1 thread1.stop (); / / outputs thread thread1 status log.info ("{}", thread1.getState ()); / / current thread hibernates for 1 second TimeUnit.SECONDS.sleep (1) / / output thread thread1 status log.info ("{}", thread1.getState ());}}
Run the code and output:
18 thread1 02Rose 15.312 [thread1] INFO com.itsoku.chat01.Demo01-start
18Rom 02Rose 16.311 [main] INFO com.itsoku.chat01.Demo01-RUNNABLE
18 TERMINATED 02 TERMINATED 17. 313 [main] TERMINATED
There is an endless loop in the code. After calling the stop method, the state of the thread thread1 changes to TERMINATED (end state), and the thread stops.
When we use idea or eclipse, we will find that this method is an obsolete method, that is, jdk may remove the method in the future.
Why is the stop method obsolete and not recommended? The stop method is so violent that it forcibly stops the method being executed.
Have you ever encountered such a scenario: when the power system needs maintenance, we are writing code, and the repairman turns off the power directly, and the code that has not been saved is not very crashed? this way is similar to calling the thread's stop method directly. The thread is running and is forced to end, which may lead to some unexpected consequences. You can send you a notice telling you to save the work at hand and turn off the computer.
Thread interrupt
In java, thread interrupt is an important thread writing mechanism. On the surface, interrupt means to stop the execution of the target thread, but in fact this is not entirely the case. In the above, we have discussed in detail the disadvantages of stopping threads with the stop method, and jdk provides a better way to interrupt threads. Strictly speaking, a thread interrupt does not cause the thread to exit immediately, but instead sends a notification to the thread informing the target thread that someone wants you to quit! It is important that it is entirely up to the target thread to decide what to do after receiving the notification. If the thread exits immediately and unconditionally after the interruption, we will go back to the old problem of the stop method.
Thread provides three methods related to thread interruption, which are easy to be confused. Please note:
Public void interrupt () / / interrupt thread public boolean isInterrupted () / determine whether the thread is interrupted public static boolean interrupted () / / determine whether the thread is interrupted, and clear the current interrupt state
The interrupt () method is an instance method that notifies the target thread of an interrupt, that is, setting the interrupt flag bit to true, which indicates that the current thread has been interrupted. The isInterrupted () method is also an instance method that determines whether the current thread is interrupted (by checking the interrupt flag bit). The last method, interrupted (), is a static method that returns the boolean type and is also used to determine whether the current thread has been interrupted, but also clears the status of the interrupt flag bit of the current thread.
While (true) {if (this.isInterrupted ()) {System.out.println ("I'm quitting!"); break;}; thread1.setName ("thread1"); thread1.start (); TimeUnit.SECONDS.sleep (1); thread1.interrupt ()
There is an endless loop in the above code. After the interrupt () method is called, the thread's interrupt flag is set to true, and the loop body determines whether the thread needs to exit by checking whether the thread's interrupt flag is ture (this.isInterrupted ()).
Take a look at another way to interrupt:
Static volatile boolean isStop = false; public static void main (String [] args) throws InterruptedException {Thread thread1 = new Thread () {@ Override public void run () {while (true) {if (isStop) {System.out.println ("I'm quitting!"); break }; thread1.setName ("thread1"); thread1.start (); TimeUnit.SECONDS.sleep (1); isStop = true;}
In the code, a variable isStop is used to control whether the thread stops.
What's the difference between interrupting a thread through variable control and the interrupt method that comes with the thread?
If a thread calls the sleep method and is dormant all the time, can the thread be interrupted by variable control? You can think about it.
At this point, the thread can only be interrupted using the interrupt method provided by the thread.
Public static void main (String [] args) throws InterruptedException {Thread thread1 = new Thread () {@ Override public void run () {while (true) {/ / dormant for 100 seconds try {TimeUnit.SECONDS.sleep (100) } catch (InterruptedException e) {e.printStackTrace ();} System.out.println ("I'm quitting!"); break;}; thread1.setName ("thread1"); thread1.start () TimeUnit.SECONDS.sleep (1); thread1.interrupt ();}
After calling the interrupt () method, the thread's sleep method will throw an InterruptedException exception.
Thread thread1 = new Thread () {@ Override public void run () {while (true) {/ / dormant for 100 seconds try {TimeUnit.SECONDS.sleep (100);} catch (InterruptedException e) {e.printStackTrace () } if (this.isInterrupted ()) {System.out.println ("I'm quitting!"); break;}
Run the above code and find that the program cannot be terminated. Why?
The code needs to be changed to:
Thread thread1 = new Thread () {@ Override public void run () {while (true) {/ / dormant for 100 seconds try {TimeUnit.SECONDS.sleep (100);} catch (InterruptedException e) {this.interrupt () E.printStackTrace ();} if (this.isInterrupted ()) {System.out.println ("I'm quitting!"); break;}
The above code can be terminated.
Note: after the sleep method throws an exception due to an interrupt, the thread's interrupt flag will be cleared (set to false), so you need to execute the this.interrupt () method in the exception, setting the interrupt flag position to true.
Wait (wait) and notify (notify)
To support collaboration between multiple threads, JDK provides two very important methods: the wait wait () method and the notify notify () method. These two methods are not in the Thread class, but are defined in the Object class. This means that all objects can call two methods.
Public final void wait () throws InterruptedException; public final native void notify ()
When the wait () method is called on an object instance, the current thread waits on that object. What does this mean? For example, in thread A, if the obj.wait () method is called, thread A stops executing and changes to a waiting state. When will the waiting end? Thread A waits until other threads call the obj.notify () method, and the obj object becomes an effective means of communication between multiple threads.
So how do the wait () method and notify () method work? Figure 2.5 shows the working process of both. If a thread calls the object.wait () method, it goes in and out of the wait queue of the object object. There may be multiple threads in this queue because the system may be running multiple threads waiting for an object at the same time. When the object.notify () method is called, it randomly selects a thread from the queue and wakes it up. I hope you will note that this choice is unfair. It is not that the thread will be selected first. This choice is completely random.
In addition to the notify () method, Object exclusive has a nofiyAll () method, which is similar to the notify () method, except that it wakes up all waiting threads in the waiting queue instead of randomly selecting one.
To emphasize here, the Object.wait () method cannot be called casually. It must be included in the corresponding synchronize statement summary, and either the wait () method or the notify () method needs to first get a monitor that is exclusive to the target. Figure 2.6 shows the workflow details of the wait () method and the nofiy () method. Where T1 and T2 represent two threads. T1 must get the monitor of the object object before correctly executing the wait () method money. The wait () method releases the monitor after it is executed. The purpose of this is to prevent all other threads waiting on the object object from executing properly because of the hibernation of T1.
Thread T2 must also obtain a monitor for the object object before the notify () method is called. Fortunately, T1 has released the monitor at this time, so T2 can successfully get the monitor for the object object. Next, T2 executes the notify () method to try to wake up a waiting thread, which is assumed to wake T1. After T1 is awakened, the first thing to do is not to execute subsequent code, but to try to regain the monitor of the object object that T1 holds before the execution of the wait () method. If temporarily unavailable, T1 must also wait for this monitor. When the monitor is successfully obtained, T1 can continue to execute in the real sense.
Let me give you an example:
Package com.itsoku.chat01; / * description:
* time:2019/7/12 17:18
* author: Wechat official account: passer-by Java, specializing in java technology sharing (taking you to play with crawlers, distributed transactions, asynchronous messaging services, task scheduling, sub-database tables, big data, etc.), please follow! * / public class Demo06 {static Object object = new Object (); public static class T1 extends Thread {@ Override public void run () {synchronized (object) {System.out.println (System.currentTimeMillis () + ": T1 start!") Try {System.out.println (System.currentTimeMillis () + ": T1 wait for object"); object.wait ();} catch (InterruptedException e) {e.printStackTrace () } System.out.println (System.currentTimeMillis () + ": T1 end!") } public static class T2 extends Thread {@ Override public void run () {synchronized (object) {System.out.println (System.currentTimeMillis () + ": T2 start,notify one thread!"); object.notify () System.out.println (System.currentTimeMillis () + ": T2 end!"); try {Thread.sleep (2000);} catch (InterruptedException e) {e.printStackTrace () } public static void main (String [] args) throws InterruptedException {new T1 (). Start (); new T2 (). Start ();}}
Running result:
1562934497212:T1 start! 1562934497212:T1 wait for object 1562934497212:T2 start,notify one thread! 1562934497212:T2 end! 1562934499213:T1 end!
Note that after T2 calls the notify method, T1 does not continue execution immediately, but waits for T2 to release the objec delivery lock and T1 successfully acquires the lock before continuing execution. So the last two lines of the log are 2 seconds apart (because T2 hibernates for 2 seconds after calling the notify method).
Note: both the Object.wait () method and the Thread.sleeep () method can keep the scene waiting for a certain amount of time. In addition to the fact that the wait () method can be awakened, another major difference is that the wait () method releases the lock on the target object, while the Thread.sleep () method does not.
Let's talk about wait (), notify (), notifyAll () to deepen our understanding:
It can be understood that there are two queues on the obj object, as shown in figure 1: Q1: waiting queue, Q2: the queue ready to acquire the lock; both queues are empty.
Obj.wait () procedure:
Synchronize (obj) {obj.wait ();}
If there are three threads, T1, T2, and T3 execute the above code at the same time, T1, T2, and T3 will enter the Q2 queue. As shown in figure 2, only these threads in the Q2 queue are qualified to compete for the lock of obj. Assuming that T1 grabs the lock, then the T2 and T3 models are waiting for the lock in Q2, and T1 enters the code block to execute the wait () method. At this time, T1 will enter the Q1 queue, and then the system will notify T2 and T3 in the Q2 queue to scramble for the lock of obj. The process of grabbing it, such as T1. Finally, T1, T2, and T3 all entered the Q1 queue, as shown in figure 3.
After the above process, thread T4 executes the notify () method, as follows: * *
Synchronize (obj) {obj.notify ();}
T4 will acquire the lock of obj, then execute the notify () method, and the system will randomly take a thread from the Q1 queue and join it to the Q2 queue. If T2 is lucky, it will be randomly arrived, and then T2 enters the Q2 queue. As shown in figure 4, the lock entering the Q2 queue is qualified to compete for the lock of obj. After the T4 thread finishes execution, the lock of obj will be released. At this time, T2 in queue Q2 will acquire the lock of obj, and then continue to execute. After execution, Q1 contains T1 and T3 Q2 queue is empty, as shown in figure 5
Then comes a T5 queue that executes the notifyAll () method, as follows:
Synchronize (obj) {obj.notifyAll ();}
two。 When the obj.wait () method is called, the current thread joins the queue queue1 and then releases the lock on the obj object
T5 will acquire the lock of obj, then execute the notifyAll () method, and the system will move all the threads in queue Q1 to Q2. As shown in figure 6, after the execution of the T5 thread is completed, the lock of obj will be released. At this time, T1 and T3 in queue Q2 will scramble for the lock of obj, and the unenhanced lock will continue to execute. After the unenhanced lock is released, the system will notify the thread in Q2 to continue to scramble for the claim, and then continue to execute. The last two queues are empty.
Suspend (suspend) and resume execution (resume) threads
There are also two methods in the Thread class, thread suspend (suspend) and continue execution (resume), which are a pair of opposite operations, and the suspended thread must wait until the resume () method operation before continuing. Two methods have been marked in the system and are not recommended.
The system does not recommend using the suspend () method to suspend a thread because the suspend () method causes the thread to pause without releasing any lock resources. At this point, any other thread that wants to access the lock occupied by it will be implicated, causing it to fail to function properly (see figure 2.7). The suspended thread cannot continue until the resume () method is performed on the corresponding thread, so that all other threads blocking on the relevant lock can continue to execute. However, if the resume () method operation is accidentally executed before the suspend () method, it may be difficult for the suspended thread to have a chance to continue execution. And, more seriously, the locks it occupies will not be released, so it may cause the whole system to work improperly. Moreover, for the suspended thread, from the state of its thread, it is still Runnable state, which will also affect the judgment of the current state of our team system.
The previous example:
/ * description:
* time:2019/7/12 17:18
* author: Wechat official account: passer-by Java, specializing in java technology sharing (taking you to play with crawlers, distributed transactions, asynchronous messaging services, task scheduling, sub-database tables, big data, etc.), please follow! * / public class Demo07 {static Object object = new Object (); public static class T1 extends Thread {public T1 (String name) {super (name);} @ Override public void run () {synchronized (object) {System.out.println ("in" + this.getName ()) Thread.currentThread (). Suspend ();} public static void main (String [] args) throws InterruptedException {T1 = new T1 ("T1"); t1.start (); Thread.sleep (100); T1 T2 = new T1 ("T2") T2.start (); t1.resume (); t2.resume (); t1.join (); t2.join ();}}
Run the code output:
In t1
In t2
We will find that the program does not end, and thread T2 is suspended, so that the program cannot end. Using the jstack command to view the thread stack information, you can see:
"T2" # 13 prio=5 os_prio=0 tid=0x000000002796c000 nid=0xa3c runnable [0x000000002867f000] java.lang.Thread.State: RUNNABLE at java.lang.Thread.suspend0 (Native Method) at java.lang.Thread.suspend (Thread.java:1029) at com.itsoku.chat01.Demo07 $T1.run (Demo07.java:20)-locked (a java.lang.Object)
Found that T2 thread was suspended in suspend0, T2 state is still RUNNABLE state, thread is obviously suspended, state or running easily lead to our team's current system for misjudgment, the code has been called resume () method, but due to the sequence of time, resume did not take effect, which led to T2 forever suspended, and forever occupied the object lock, which may be fatal for the system.
Wait for thread end (join) and humility (yeild)
In many cases, the input of one thread may be very dependent on the output of one or more threads, and at this point, the thread needs to wait for the dependent thread to finish execution before continuing. Jdk provides a join () operation to implement this function. The two join () methods are shown as follows:
Public final void join () throws InterruptedException; public final synchronized void join (long millis) throws InterruptedException
The first method represents an infinite wait, and it will always be just the current thread. Know that the target thread has finished executing.
The second method has a parameter that specifies the wait time, and if the target thread is still executing after the given time, the current thread will stop waiting and continue to execute.
For example, if thread T1 needs to wait for T2 and T3 to complete before continuing execution, then the join () method of T2 and T3 needs to be called in T1 thread.
Previous example:
/ * description:
* time:2019/7/12 17:18
* author: Wechat official account: passer-by Java, specializing in java technology sharing (taking you to play with crawlers, distributed transactions, asynchronous messaging services, task scheduling, sub-database tables, big data, etc.), please follow! * / public class Demo08 {static int num = 0; public static class T1 extends Thread {public T1 (String name) {super (name);} @ Override public void run () {System.out.println (System.currentTimeMillis () + ", start" + this.getName ()); for (int I = 0 I < 10; iTunes +) {num++; try {Thread.sleep (200);} catch (InterruptedException e) {e.printStackTrace () } System.out.println (System.currentTimeMillis () + ", end" + this.getName ());} public static void main (String [] args) throws InterruptedException {T1 = new T1 ("T1"); t1.start (); t1.join () System.out.println (System.currentTimeMillis () + ", num =" + num);}}
Execution result:
1562939889129instruction start t1 1562939891134end t1 1562939891134jinnum = 10
The result of num is that the timestamps of lines 1 and 3 differ by about 2 seconds, indicating that the main thread waits for T1 to complete before continuing execution.
Another method is Thread.yield (), which is defined as follows:
Public static native void yield ()
Yield means humility, this is a static method, once executed, it will allow the current thread to transfer CPU, but it should be noted that the transfer of CPU does not mean that the current thread will not allow the execution of the current thread. After the transfer of CPU, the current thread will also compete for CPU resources, but it may not be possible to seize the executive power of CPU. Therefore, the call to the Thread.yield () method seems to say: I've done some major work, I can take a break and let CPU give other threads some work opportunities.
If you feel that a thread is not very important or has a low priority, and you are worried that this thread will take up too much CPU resources, you can call the Thread.yield () method at the appropriate time to give other threads more opportunities.
This is the end of the content of "what are the basic operations of java highly concurrent threads". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.