In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
What this article shares to you is about how to carry on the analysis of the concept and principle of Java multithreading. The editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article.
What is the concept of processes and threads first?
A process is a running application, each process has its own independent memory space, a process can start multiple threads, and a thread refers to an execution process in the process, which can also be understood as a piece of code. For example, many threads can be run in a java.exe process, threads always belong to a process, and multiple threads in the process share the memory of the process.
In order to create a new thread in Java, you must specify the code that the thread is going to execute. Multithreaded programming is facilitated through the java.lang.Thread class provided by Java, which provides a large number of methods for us to control our own threads. So how does the code execute through the Java thread?
The most important run () method is provided in the Thread class, which is called by the start () method of the Thread class to provide us with the code to be executed by the thread. We just need to rewrite the method in order to execute our own code.
Method 1: inherit the Thread class and override the run () method
The subclass that creates the Thread class inherits the object overriding the run () method, as shown in the following code example:
The above method is simple and clear in line with everyone's writing habits, but there is a big disadvantage, that is, if our class is already a subclass of other classes, we can no longer inherit the Thread class, at this time, if we do not want to create a new class, what should we do?
We can only pass our method as an argument to an instance of the Thread class, similar to a callback function, but Java does not have a pointer, and we can only pass an instance that contains the method. Java uses the interface java.lang.Runnable to solve this problem.
The Runnable interface has only one run () method, which declares that the class implements the Runnable interface and provides this method to write thread code into this method to complete the task, but the Runnable interface does not have any support for threads, so you must create an instance of the Thread class through the constructor of the Thread class.
Method 2: implement the Runnable API. The code example is as follows:
Using the Runnable interface to implement multithreading enables us to contain all the code in a class, which is beneficial to encapsulation. The disadvantage is that you can only use one set of code, and if you want to create multiple threads and have each thread execute different code, you still have to create additional classes, which in most cases may not be as convenient as directly inheriting Thread from multiple classes. To sum up, the two methods to achieve multithreading have their own advantages, and we can use them flexibly.
Let's analyze some common problems in the use of multithreading.
One: threads can be divided into seven states (some people think that there are only five, and it is also correct to regard lock pool and wait pool as special cases of blocking state, but the separation of lock pool and wait pool is beneficial to the understanding of the program).
1. Initial state, thread creation, thread object call start () method
2. Runnable status, that is, the status of waiting for CPU resources to run
3. Running status, obtaining CPU resources, running status
4. Blocking state, that is, giving up CPU resources, enters a waiting state, and it is not runnable. There are three cases that will enter blocking state.
1) if you wait for the input (the input device processes it, but the CUP does not), the block is placed until the input is complete, and the blocking will enter the runnable state after the end of the blocking.
2) Thread hibernates, and the thread object calls the sleep () method. After the blocking ends, the thread will enter the runnable state.
3) Thread object 2 calls the join () method of thread object 1, and thread object 2 enters a blocking state until thread object 1 is aborted.
5. Abort status, that is, the end of execution
6. Lock pool status
7. Waiting queue
Two: thread priority
The priority of a thread represents the importance of the thread. When multiple threads are executable at the same time and wait for CPU time, the thread scheduling system decides who to allocate CPU time according to the priority of each thread. The thread with high priority has a greater chance of getting CPU time, while the thread with lower priority has less chance of getting CPU time. Call the getPriority () and setPriority () methods of the Thread class to access the priority of the thread, which is between 1 (MIN_PRIORITY) and 10 (MAX_PRIORITY), and the default is 5 (NORM_PRIORITY).
Three: thread synchronization
Because multiple threads of the same process share the same storage space, it not only brings convenience, but also brings serious access conflicts. Java language provides a special mechanism to resolve this conflict, which effectively prevents the same data object from being accessed by multiple threads at the same time. Since we can use the private keyword to ensure that data objects can only be accessed by methods, we only need to propose a mechanism for methods, which is the synchronized keyword, which includes two uses: synchronized methods and synchronized blocks.
1. Declare the synchronized method by adding the synchronized keyword to the method declaration. Such as: public synchronized void accessVal (int newVal); synchronized method controls access to class member variables: each class instance corresponds to a lock, and each synchronized method must obtain a lock of the class instance that calls the method before execution, otherwise the thread to which it belongs will block, the method will monopolize the lock once executed, and the lock will not be released until it is returned from the method, and then the blocked thread can acquire the lock and re-enter the executable state.
This mechanism ensures that for each class instance, at most one of its member functions declared as synchronized is in the executable state at the same time, thus effectively avoiding the access conflicts of class member variables. In Java, there are not only class instances, but also a lock for each class, so we can also declare the static member function of the class as synchronized to control its access to the static member variables of the class.
The drawback of the synchronized method: declaring a large method as synchronized will greatly affect efficiency. Typically, if you declare the run () method of a thread class as synchronized, because it has been running throughout the lifetime of the thread, it will never make a successful call to any synchronized method of this class. Of course, we can solve this problem by declaring the code that accesses the class member variables as synchronized in a special method and calling it in the main method, but Java provides us with a better solution, which is the synchronized block.
two。 Declare the synchronized block with the synchronized keyword, the syntax is as follows:
Synchronized (syncObject) {
/ / allow access control code
}
A synchronized block is a code block in which the code must acquire a lock on the object syncObject (class instance or class) before it can be executed. Because you can target any block of code and arbitrarily specify locked objects, it is more flexible.
Four: thread blocking
In order to resolve access conflicts to the shared storage area, Java introduces a synchronization mechanism. Blocking refers to pausing the execution of a thread to wait for a condition to occur (such as a resource is ready). Java provides a number of ways to support blocking, which is analyzed one by one:
1. The sleep () method: sleep () allows you to specify a period of time in milliseconds as a parameter, which makes the thread enter the blocking state within the specified time, and cannot get the CPU time. After the specified time, the thread returns to the executable state.
2. Suspend () and resume () methods: the two methods are used together, suspend () so that the thread into the blocking state will not automatically recover, the corresponding resume () must be called in order to make the thread re-enter the executable state.
3. The yield () method: yield () causes the thread to give up the current allocated CPU time, but does not block the thread, that is, the thread is still in an executable state and may be allocated CPU time again at any time. The effect of calling yield () is equivalent to the fact that the scheduler believes that the thread has executed enough time to go to another thread.
4. Wait () and notify () methods: two methods are used together, wait () makes the thread into a blocking state, it has two forms, one allows you to specify a period of time in milliseconds as a parameter, the other has no parameters, the former re-enters the executable state when the corresponding notify () is called or exceeds the specified time, while the latter must call the corresponding notify (). Note that neither of the 123 steps will release the occupied lock while this pair of methods will release the occupied lock.
There are two last points about the wait () and notify () methods:
1) the thread that calls the notify () method to unblock is randomly selected from the thread that is blocked by calling the wait () method of the object, so we can't predict which thread will be selected, so we should be very careful when programming to avoid problems caused by this uncertainty.
2) in addition to notify (), there is a notifyAll () method that works similarly, except that calling the notifyAll () method unblocks all threads blocked by calling the object's wait () method at once. Of course, only the thread that acquired the lock can enter the executable state.
When it comes to blocking, we have to talk about the concept of deadlock. After a little analysis, we can find that calls to the suspend () method and the wait () method that does not specify a time-out period can produce deadlocks. Unfortunately, Java does not support deadlock avoidance at the language level, so we must be careful to avoid deadlocks in programming.
Five: daemon thread
The daemon thread is a special kind of thread, which is different from the ordinary thread in that it is not the core part of the application. When all the non-daemon threads of an application stop running, even if there are still daemon threads running, the application will also be terminated, on the contrary, as long as there is a non-daemon thread running the application will not be terminated. Daemon threads are generally used to provide services to other threads in the background. You can determine whether a thread is a daemon by calling the isDaemon () method, and you can call the setDaemon () method to set a thread as a daemon thread.
Six: thread group
Thread group is a unique concept of Java. In Java, thread group is the object of ThreadGroup class, and each thread belongs to a unique thread group, which is specified when the thread is created and cannot be changed throughout the thread's lifetime. You can specify the thread group to which the thread belongs by calling the Thread class constructor that contains the ThreadGroup type parameter. If not specified, the thread belongs by default to the system thread group named system.
In Java, except for the pre-built system thread groups, all thread groups must be explicitly created and each thread group belongs to another thread group. When you create a thread group, you can specify which thread group it belongs to, or by default it belongs to the system thread group if it is not specified. In this way, all thread groups form a tree rooted in the system thread group.
Java thread group instance code, as shown below:
Source code reference: http://blog.yoodb.com/yoodb/article/detail/1330
Java allows us to operate on all threads in a thread group at the same time, for example, we can set the priority of all threads in the thread group by calling the corresponding methods of the thread group, or we can start or block all threads in it.
Another important role of Java's thread group mechanism is thread safety. Thread group mechanism allows us to distinguish threads with different security characteristics by grouping, to deal with threads in different groups differently, and to support the adoption of unequal security measures through the hierarchical structure of thread groups. Java's ThreadGroup class provides a number of methods to make it easy for us to manipulate every thread group in the thread group tree and every thread in the thread group.
The above is how to analyze the concept and principle of Java multithreading. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.
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.