Java Threading Foundation
Phase to recommend
- Learn more about Java exceptions
- Java Basics: The Object class
- Do you understand these frequent meeting questions of the Object class?
- Spring common API: Spring class and related surface pilot
1. Processes and threads
- Process: is a computer program on a data set of a run of the basic unit of system resource allocation and scheduling, is the foundation of the operating system structure.
- Thread: The basic unit by which the system allocates processor time resources. It is an execution task in a process. Threads execute independently in a program. A process contains at least one thread. A process can run multiple threads, and multiple threads can share data.
2. Differences between processes and threads
- Fundamental differences: A process is the basic unit of resource allocation in the operating system, while a thread is the basic unit of task scheduling and execution in the processor.
- Resource overhead: Each process has its own code and data space (program context), and switching between processes can be costly. Threads of the same class share code and data space in the process. Each thread has its own run stack and program counter (PC). Switching between threads is cheap.
- Containment: A process contains multiple threads that share the resources and address space occupied by the process.
- Memory allocation: Threads of the same process share the data and address space of the same thread, and the data and address space of different processes are independent of each other.
- Communication mode: Processes can communicate with each other through channels, message queues, shared memory, semaphore, Socket and other mechanisms. Threads can communicate with each other mainly through shared variables and their variants.
- Influence relationship: The child process cannot control the parent process. When an exception occurs in one process, other processes are not affected. The child thread can control the parent thread, and if the main thread fails, the process in which the child thread runs and the rest of the threads are affected.
- Execution process: Each independent process has an entry point for the program to run, a sequence of execution and an exit. But the thread cannot execute independently, must depend on the application program, by the application program provides multiple thread execution control, both can execute concurrently.
3. Concurrency and concurrency
- Concurrency: When multiple tasks on the same CPU are executed in turn in subdivided time slices, these tasks are logically executed simultaneously.
- Parallel: Multiple cpus or multi-core cpus work on multiple tasks at the same time, effectively executing at the same time.
4. Four ways to create a thread
- inheritance
Thread
类 - implementation
Runnable
interface - implementation
Callable
interface - use
Executors
The utility class creates a thread pool
Through inheritanceThread
Class to create a thread:
- define
Thread class
And overwrite the classrun()
Method, whichrun()
Method is executed as the body of the thread. - create
Thread
An instance of a subclass that creates a thread object. - Calling the thread object
start()
Method to start the thread.
- Thread class source:
public class Thread implements Runnable {
private static native void registerNatives();
static {
registerNatives();
}
private volatile String name;
private int priority;
private Thread threadQ;
private long eetop;
Copy the code
- The instance
public class ThreadTest extends Thread {
private int i;
@Override
public void run() {
for(; i < 2; i++) {
System.out.println("Inherit Thread to start the Thread:" + getName() + ":" + i);
}
setName("Thread-new");
for(; i < 4; i++) {
System.out.println("Rename the new thread name:" + Thread.currentThread().getName() + ":" + i);
}
}
public static void main(String[] args) {
System.out.println("Main thread:" +Thread.currentThread().getName());
newThreadTest().start(); }}Copy the code
By implementingRunnable
Interface to create a thread:
- define
The Runnable interface
And implements the interfacerun()
Method, whichrun()
Method is executed as the body of the thread. - create
A Runnable implementation class
As an example ofThread
Target to createThe Thread object
, the Thread object is a Thread object. - Calling the thread object
start()
Method to start the thread.
public class MyThread extends OtherClass implements Runnable {
public void run() {
System.out.println("MyThread.run()");
}
// Start MyThread by instantiating a Thread and passing in its own instance of MyThread:
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
// In fact, Thread's run() method is called when a Runnable target is passed to Thread
target.run();
public void run() {
if(target ! =null) { target.run(); }}Copy the code
By implementing Callable
Interface to create a thread:
- create
Callable interface
The implementation class and the implementationcall()
Method, whichcall()
Method is executed as the thread body, and thecall()
Method has a return value. Then create an instance of the Callable implementation class. - use
FutureTask class
To wrap the Callable object. The FutureTask object wraps the Callable object’scall()
Method. - use
FutureTask object
As aThe Thread object
The target of creates and starts new threads. - call
FutureTask object
theget()
Method to get the value returned by the child thread at the end of execution.
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread myThread = new MyThread();
// The adaptation class FutureTask
FutureTask futureTask = new FutureTask(myThread);
new Thread(futureTask,"A thread." ").start();
new Thread(futureTask,Thread "B").start();// Start two threads, which will be cached, and execute only once
new Thread(futureTask).start();
Object o = futureTask.get();
System.out.println(o);
}
// What type is a generic and what type is the return value of the method implemented by the interface
static class MyThread implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("Create a thread with Callable");
return "Return value for creating thread using Callable"; }}Copy the code
The advantages and disadvantages of using Runnable and Callable interfaces to create multithreading:
- The thread class only implements the Runnable or Callable interfaces, and can inherit from other classes.
- In this way, multiple threads can share the same target object, so it is very suitable for multiple threads to process the same resource, so that the CPU, code and data can be separated to form a clear model, which better reflects the object-oriented idea.
- On the downside, the programming is slightly more complex, and if you want to access the currentThread, you must use the thread.currentthread () method.
The pros and cons of using the Thread class to create multiple threads:
- The disadvantage is that since the Thread class already inherits from Thread, it cannot inherit from any other parent class.
- The advantage is that it’s easy to write, and if you need to access the currentThread, you don’t need to use thread.currentthread (), just use this to get the currentThread.
Given the above analysis, it is generally recommended to implement the Runnable and Callable interfaces to create multithreading.
useExecutors
The utility class creates a thread pool
public class ThreadPoolTest {
public static void main(String[] args) {
// Create a thread pool
ExecutorService threadPool = Executors.newFixedThreadPool(10);
while(true) {
threadPool.execute(new Runnable() { // Submit multiple threaded tasks and execute them
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " is running ..");
try {
// Thread sleep, sleep is not release lock, always occupy
Thread.sleep(3000);
// The lock is released
System.out.println(Thread.currentThread().getName() + "End sleep");
} catch(InterruptedException e) { e.printStackTrace(); }}}); }}}Copy the code
5. Thread life cycle
- The thread state transition is shown below:
1. New initial state, the state of the thread when it was created, that is, a New thread object created by the New keyword.
Java refers to a thread’s ready state and its running state as the Runnable state.
The thread is Blocked from running because it abandonedthe CPU usage for some reason. In other words, it gives up the CPU timeslice and stops running temporarily. There is no chance to get the CPU Timeslice to the running state again until the thread enters the runnable state. There are three types of blocking:
- Wait block: When a running thread calls the O.wait method, the JVM puts it in the Waitting Queue and the thread becomes blocked.
- Synchronization blocking: When a running thread attempts to acquire a synchronization Lock on an object that is being held by another thread, the JVM puts that thread into the Lock Pool and the thread becomes blocked.
- Other blocking: The JVM converts a running Thread to blocking when it executes thread.sleep (long MS), thread.join (), or makes an I/O request. The Thread does not return to the runnable state until the sleep() state times out, thread.join () waits for the Thread to terminate or time out, or I/O processing is complete.
A state in which a thread has to wait for another thread to perform some specific action, such as a thread notification or a thread interrupt, and must be awakened to have a chance to execute. Otherwise, the thread in this state will wait indefinitely.
5. Timed_Waiting is different from the waiting state. Threads in the timeout wait state can automatically wake up after a specified period of time
A thread is in the Terminated state after it has finished performing the required tasks.
The difference between sleep () and wait ()
-
Sleep () is a static method in Thread, while wait() is a member method in Object.
-
Wait (), notify(), and notifyAll() can only be used in synchronous methods or blocks of synchronized code, whereas sleep can be used anywhere.
-
Sleep () does not release the lock, while wait() does and needs to reacquire the lock via notify()/notifyAll().
-
Wait () is usually used for interthread interaction/communication, and sleep() is usually used to suspend execution.
-
The sleep() method must catch an exception. In the process of calling sleep(), it is possible that its interrupt() will be called by another object, thus producing InterruptedException. If the program does not catch this exception, the thread will terminate abnormally. Enter the Terminated state. Wait (), notify(), and notifyAll() do not need to catch exceptions. The wait() method interrupts the wait state of the thread with the interrupt() method, and the thread immediately throws an interrupt exception.
7. What’s the difference between a thread’s sleep() and yield() methods?
(1) The sleep() method does not consider the priority of the thread when it gives other threads a chance to run, so it gives low-priority threads a chance to run; The yield() method only gives threads of the same or higher priority a chance to run;
(2) The thread is in the blocked state after executing the sleep() method, and in the ready state after executing the yield() method;
(3) The sleep() method declares that it throws InterruptedException, while the yield() method declares no exceptions;
(4) The sleep() method is more portable than the yield() method (related to operating system CPU scheduling), and yield() is generally not recommended to control the execution of concurrent threads.
8. Methods for thread synchronization and thread scheduling
sleep()
: puts a running thread to sleep without releasing the lockwait()
: is when a thread is in the wait state and releases the held lock object.notify()
: Wakes up a thread in the waiting state. This method does not wake up a specific thread, but the JVM decides which one to wake up, regardless of priority.notifyAll()
: Wakes up all threads in the waiting state. Instead of locking the object to all threads, this method lets them compete. Only the threads competing for the locked object can enter the ready state and wait for the CPU to schedule.
9. How do I stop a running thread?
-
With the exit flag, the thread exits normally, i.e. terminates when the run () method completes.
-
Suspend is enforced using the stop () method, but it is not recommended because stop () is an expired method just like suspend () and resume ().
-
Interrupt the thread using the interrupt () method.
10. How do I wake up a blocked thread?
- First, wait(),notify() are for objects. A call to wait() on any object will block the thread and release the lock object. Correspondingly, a call to notify() on any object will randomly release the blocked thread, but only if the blocked thread retrieves the lock object. So we can move on.
- Second, the wait(),notify() methods must be called from within the synchronize method or block, and the lock object of the synchronized block or method must be the same as the object on which wait() and notify() methods were called. In this case, before wait() is called, the current thread has acquired the lock on an object. After wait() is executed, the current thread blocks and releases the previously acquired lock.
11. Why are stop() and suspend() methods not recommended
- The stop method terminates all outstanding methods, including the run method. When a thread wants to terminate another thread, it has no way of knowing when it is safe to call stop and when it will cause the object to be corrupted. So this method was deprecated. You should interrupt a thread, not stop it.
- Suspend is deprecated because it causes deadlocks. The suspend method, unlike the stop method, does not break an object to force the lock to be released. Instead, it retains possession of the lock until another thread calls the resume method before it can proceed. If have A, B two threads, A thread was suspend obstruction after obtain A lock, at this time A can’t continue, thread B after get the same lock can call resume method will be A wake up, but this time the lock is A possession, B cannot continue, also cannot timely awaken A, at this point A, B Neither thread can continue execution downwards and a deadlock is formed.
12. The difference between start and run
- The start () method is used to start the thread from its initial state to the ready state. Instead of waiting for the run body to complete, you can directly continue executing the following code.
- To start a Thread by calling the start() method of the Thread class, the Thread is in the ready state and is not running.
- The run() method is called the thread body. It contains the contents of the thread to be executed. When the CPU is scheduled to execute on the current thread, the current thread enters the running state and starts running the code in the run function. The Run method finishes, the thread terminates, and the CPU schedules other threads.
13. Join (), join ()
YieId ()
This method is used to enable the current thread to yield its CPU usage and switch from the running state to the running state. However, it is not guaranteed that other threads can obtain the CPU execution right, because the current thread still has the chance to obtain the CPU execution right after the current thread becomes the running state after executing the yield() method.
The join ()
Add the specified thread to the current thread, and let one thread wait until the other thread finishes executing. You can merge two alternate threads into sequential threads.
.try {
threadA.start();
threadA.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// The current thread waits for threadA to finish executing before proceeding.Copy the code
14. How to implement thread synchronization?
1. Synchronization method
That is, methods that are modified with the synchronized keyword, since every Java object has a built-in lock that protects the entire method when modified with this keyword. The built-in lock needs to be acquired before the method can be called, otherwise it is blocked. Note that the synchronized keyword can also modify static methods, which, if called, would lock the entire class.
2. Synchronize code blocks
That is, a statement block that is modified by the synchronized keyword. A built-in lock is automatically added to the synchronized statement block. It is important to note that synchronization is an expensive operation, so it should be minimized. It is usually not necessary to synchronize entire methods; synchronized code blocks can be used to synchronize key code.
3. ReentrantLock
Java 5 has added a java.util.Concurrent package to support synchronization, where the ReentrantLock class is a reentrant, mutually exclusive, Lock that implements the Lock interface, which has the same basic behavior and semantics as using synchronized methods and fast, and extends its capabilities. Note that ReentrantLock also has a constructor that can create a fair lock, but it is not recommended because it can greatly reduce the efficiency of the application.
4. volatile
The volatile keyword provides a lock-free mechanism for accessing field variables. Using volatile to modify a field tells the VIRTUAL machine that the field may be updated by other threads and therefore should be recalculated each time the field is used, rather than using the value in the register. It is important to note that volatile does not provide any atomic operations, nor can it be used to modify variables of final type.
Atomic variables
A utility class that creates variables of atomic type is provided in the Java util.concurrent.atomic package to simplify thread synchronization. For example, the AtomicInteger table can update the value of an int atomically, which can be used in applications (such as atomically incrementing counters), but cannot be used to replace an Integer. Extensible Number to allow uniform access to tools and utilities that deal with the opportunity Number class.
15. Difference between notify() and notifyAll()
- notify()
Used to wake up a thread that is waiting for the corresponding object lock and put it on the ready queue so that it can compete for the lock after the current thread releases it and get the CPU to execute.
- notifyAll()
This is used to wake up all threads that are waiting for the corresponding object lock and put them on the ready queue so that they can compete for the lock after the current thread releases it and get the CPU to execute.
16. The thread is interrupted
An interrupt is an identifier property of a thread that indicates whether a running thread has been interrupted by another thread. Interrupts only inform, not force, a thread to exit.
- Interrupt () interrupts the thread and interrupted() detects the thread status and clears the thread interrupt status.
public class InterruptDemo {
public static void main(String[] args) {
Thread thread = Thread.currentThread();
// The thread is interrupted by the interrupted() method
System.out.println(thread.getName()+"Thread - Interrupt or not:"+thread.interrupted());
// Set the current thread interrupt
Thread.currentThread().interrupt();
The interrupted() method determines whether the thread has been interrupted, which clears the thread state
System.out.println(thread.getName()+"Thread - Interrupt or not:"+thread.interrupted());/ / return true
// Check whether the Interrupted () method clears the thread state ----> Yes
System.out.println(thread.getName()+"Thread - Interrupt or not:"+thread.interrupted()); / / returns false}}Copy the code
- Interrupt () interrupts the thread and isInterrupted() detects the thread state and does not clear the thread interrupt status
public class InterruptDemo {
public static void main(String[] args) {
Thread thread = Thread.currentThread();
// The thread is interrupted by the interrupted() method
System.out.println(thread.getName()+"Thread - Interrupt or not:"+thread.interrupted());
// Set the current thread interrupt
Thread.currentThread().interrupt();
The isInterrupted() method does not clear the status of the thread
System.out.println(thread.getName()+"Thread - Interrupt or not:"+thread.isInterrupted());/ / return true
// Check whether the isInterrupted() method clears the thread state ----> No
System.out.println(thread.getName()+"Thread - Interrupt or not:"+thread.isInterrupted()); / / return true}}Copy the code
17. The difference between interrupted () and isInterrupted ()
interrupt
: Used to interrupt a thread. The thread whose state is calling this method will be put in the “interrupted” state.
It is important to note that thread interrupts only set the interrupt status bit of the thread, and do not stop the thread. It is up to the user to monitor the state of the thread and do the processing. A method that supports thread interrupts (that is, one that throws interruptedException when the thread interrupts) monitors the thread’s interrupted status and throws an interrupt exception if the thread’s interrupted status is set to “interrupted.”
interrupted
: static method that checks whether the current interrupt signal is true or false and clears the interrupt signal. If a thread has been interrupted, the first call to the Interrupted thread returns true, and the second and subsequent calls return false.
isInterrupted
: Check whether the current interrupt signal is true or false.
18. Why is the run() method executed when we call start(), and why can’t we call run() directly?
New A Thread. The Thread enters the new state. Calling the start() method starts a thread and puts it in the ready state, ready to run when the time slice is allocated. Start () performs the corresponding preparation of the thread, and then automatically executes the contents of the run() method, which is really multithreaded work. However, directly executing the run() method will execute the run() method as if it were a normal method in the main thread, and will not execute it in a thread, so it is not multi-threaded.
Conclusion: A call to start() starts the thread and puts it in the ready state. A direct run() does not execute in multithreaded fashion.