1. Threads and processes
- A process is an entity. Each process has its own address space, generally includingText region, data region and stack region. The text area stores the code executed by the processor; the data area stores variables and dynamically allocated memory used during process execution; the stack area stores instructions and local variables for active procedure calls.
- A standard thread consists of a thread ID, current instruction pointer (PC), a set of registers, and a stack. In addition, a thread is an entity in the process and is the basic unit that is independently scheduled and dispatched by the system. The thread itself does not own the system resources, but only has a few essential resources during operation, but it can share all the resources owned by the process with other threads belonging to the same process.
- Different differences
a, Address space: an execution unit within the process; the process has at least one thread; they share the process's address space; and the process has its own independent address space;
b. Resource ownership: a process is the unit of resource allocation and ownership, and threads within the same process share the resources of the process
c. Threads are the basic unit of processor scheduling, but processes are not.
d, both can be executed concurrently.
2. Daemon thread
There are two types of threads in Java: User Thread and Daemon Thread.
The difference between a daemon thread and a user thread is that the daemon thread depends on the thread that created it, while the user thread does not depend on it. To give a simple example: if a daemon thread is created in the main thread, the daemon thread will also die after the main method is completed. The user thread does not, and the user thread will run until it is completed. In JVM, a garbage collector thread is a daemon thread.
3. Java thread status
- NEW status means that the thread has just been created and has not been started yet
- RUNNABLE Java threads will generally become "running" in two states: ready and running. After the thread object is created, other threads (such as main thread) call the start() method of the object. The thread in this state is located in the runnable thread pool, waiting to be selected by the thread schedule, obtaining the right to use the CPU, and is in the ready state (ready). The thread in the ready state becomes running after obtaining the CPU time slice.
- In this state, it is a scenario where multiple threads have synchronous operations, such as waiting for the execution and release of the synchronized block of another thread, that is, the thread is waiting to enter the critical area.
- WAITING In this state, after a thread owns a certain lock, it calls its wait method, waiting for other threads/lock owners to call notify/notifyAll. The thread can continue to operate in the next step. Here we need to distinguish the difference between BLOCKED and WATING. One is waiting outside the critical point to enter, and the other is waiting for others notify in the understanding point. When the thread calls the join method and joins another thread, it will also enter the WAITING state, waiting for the execution of the thread that joins the end.
- TIMED_WAITING This state is a limited (time limit) WAITING, which usually occurs when waiting(long), join(long), etc. After another thread sleeps, it will also enter the TIMED_WAITING state.
- TERMINATED In this state, the thread's run method has been executed, which is basically equivalent to death (if the thread is persistently held, it may not be recycled)
4. Please tell us the methods related to thread synchronization and thread scheduling.
- wait(): Make a thread in a waiting (blocking) state,and release the lock of the object held;
- sleep(): Make a running thread sleep state, it is a static method, and calling this method is to handle the InterruptedException exception;
- notify(): Wake up a thread in a waiting state. Of course, when calling this method, it cannot exactly wake up a thread in a waiting state. Instead, the JVM determines which thread to wake up, and it has nothing to do with priority;
- notityAll(): wakes up all threads in a waiting state. This method does not lock the object to all threads, but allows them to compete. Only threads that obtain the lock can enter the ready state;
5. Process scheduling algorithm
Real-time system: FIFO (First Input First Output, first-in, first-out algorithm), SJF (Shortest Job First, shortest job priority algorithm), SRTF (Shortest Remaining Time First, shortest remaining time priority algorithm).
Interactive system: RR (Round Robin, time slice rotation algorithm), HPF (Highest Priority First), multi-level queue, shortest process priority, guaranteed scheduling, lottery scheduling, fair sharing scheduling.
6. The difference between wait() and sleep()
- sleep comes from Thread class, and wait comes from Object class
- During the call to the sleep() method, the thread will not release the object lock. And calling the wait method thread will release the object lock
- After sleeping, no system resources are given, wait to give up system resources and other threads can occupy the CPU
- sleep(milliseconds) requires a sleep time, and it will automatically wake up as soon as the time arrives.
7. ThreadLocal and deadlock analysis
hreadLocal maintains a local variable for each thread.
Use space to exchange time, which is used for data isolation between threads, providing a copy for each thread that uses this variable. Each thread can independently change its own copy without conflicting with the copy of other threads.
The ThreadLocal class maintains a Map that stores a copy of variables for each thread. The key of the element in the Map is a thread object, and the value is a copy of the variables for the corresponding thread.
ThreadLocal memory overflow code demonstration and cause analysis!
8. Synchronized and Lock
-
ReentrantLock has the same concurrency and memory semantics as Synchronized, and there are also many lock voting, timed lock waiting and interrupt lock waiting.
Both threads A and B need to obtain the lock of object O. Assuming that A acquires the lock of object O, B will wait for A to release the lock of O.
If synchronized is used, if A is not released, B will wait and cannot be interrupted
If using ReentrantLock, if A is not released, B can interrupt the waiting after waiting for a long enough time and do other things -
ReentrantLock acquires locks in three ways:
a) lock(), if the lock is acquired, return immediately. If another thread holds the lock, the current thread will remain in a dormant state until the lock is acquired.
b) tryLock(), if the lock is acquired, it will return true immediately, and if another thread is holding the lock, it will return false immediately;
c) tryLock(long timeout,TimeUnit unit), if the lock is acquired, it will return true immediately. If another thread is holding the lock, it will wait for the given time of the parameter. During the waiting process, if the lock is acquired, it will return true, and if the waiting timeout, it will return false;
d) lockInterruptibly: If the lock is acquired, return immediately. If the lock is not acquired, the current thread is in a dormant state until either locked, or the current thread is interrupted by another thread
The overall conclusion is first presented:
synchronized:
When the competition for resources is not very fierce and there is occasional synchronization, synchronized is very suitable. The reason is that compiled programs usually optimize synchronized as much as possible, and in addition, they are very readable, which can be understood by programmers who have not used more than 5.0 thread packages.
ReentrantLock:
ReentrantLock provides diversified synchronization, such as time-limited synchronization, which can be synchronized by Interrupt (synchronized synchronization cannot be interrupted). In the case of low resource competition, the performance is slightly worse than synchronized. However, when the synchronization is very intense, the performance of synchronized can drop dozens of times at once. ReentrantLock can indeed maintain normalcy.
9. Volatile and Synchronized
Volatile and Synchronized four differences:
- Different granularity, the former is for variables, and the latter is for objects and classes
- Syn blocks, volatile threads do not block
- Syn ensures three major characteristics, volatile does not guarantee atomicity
- syn compiler optimization, volatile is not optimized
To make the volatile variable ideal thread safety, the following two conditions must be met at the same time: - Write operations to variables do not depend on the current value.
- This variable is not included in the invariant with other variables.
Comparison between volatile and synchronized in JAVA multi-threading
10、CAS
CAS is an optimistic locking technology. When multiple threads try to use CAS to update the same variable at the same time, only one of the threads can update the value of the variable, while the other threads fail. The failed thread will not be suspended, but will be told that this competition has failed and can try again. CAS has 3 operands, memory value V, old expected value A, and new value B to be modified. Modify the memory value V to B if and only if the expected value A and memory value V are the same, otherwise do nothing.
11. Detailed explanation of Unsafe class in Java
- The Unsafe class can allocate memory and free memory; the three local methods provided in the class are used to allocate memory, expand memory and free memory, respectively, which correspond to the three methods in C language.
- You can locate the memory location of a field in an object, or modify the field value of the object, even if it is private;
- Suspend and restore: suspending a thread is achieved through the park method. After calling park, the thread will block until conditions such as timeout or interrupt appear. unpark can terminate a pending thread to restore it to normal. The suspend operation on threads in the entire concurrency framework is encapsulated in the LockSupport class. There are various versions of pack methods in the LockSupport class, but in the end all the() method is called.
- cas
Detailed explanation of Unsafe class in Java
12. Thread pool
The function of thread pool:
When the program starts, several threads are created to respond and process. They are called thread pools, and the threads inside are called worker threads
First: Reduce resource consumption. Reduce the consumption caused by thread creation and destruction by reusing created threads.
Second: Improve response speed. When a task arrives, the task can be executed immediately without waiting for thread creation.
Third: Improve thread manageability.
Common thread pool: ExecutorService is the main implementation class, among which commonly used are
hreadPool(),newFixedThreadPool(),newcachedTheadPool(),newScheduledThreadPool()。
13、ThreadPoolExecutor
###Constructor method parameter description
corePoolSize: The number of core threads. By default, the core thread will survive and will not be restricted by keepAliveTime even if it is idle. Unless allowCoreThreadTimeOut is set to true.
maximumPoolSize: The maximum number of threads that a thread pool can accommodate. Threads exceeding this number will be blocked. This value is invalid when the task queue is a LinkedBlockingDeque with no set size.
keepAliveTime: The idle timeout time of non-core threads, if it exceeds this time, it will be recycled.
unit: Specify the unit of keepAliveTime, such as. Effective on corePoolSize when allowCoreThreadTimeOut is set to true.
workQueue: Task queue in thread pool.
There are three commonly used queues, SynchronousQueue, LinkedBlockingDeque, and ArrayBlockingQueue.
threadFactory: thread factory, providing the function of creating new threads. ThreadFactory is an interface with only one method
principle
- If the current pool size poolSize is smaller than corePoolSize , a new thread is created to execute the task.
- If the current pool size poolSize is greater than corePoolSize and the waiting queue is not full, then the waiting queue will enter the waiting queue
- If the current pool size poolSize is greater than corePoolSize and is less than maximumPoolSize and the waiting queue is full, a new thread is created to execute the task.
- If the current pool size poolSize is greater than corePoolSize and is greater than maximumPoolSize and wait for the queue to be full, a rejection policy is called to handle the task.
- Each thread in the thread pool will not exit immediately after executing the task, but will check whether there are still thread tasks in the waiting queue to be executed. If you cannot wait for a new task in keepAliveTime, the thread will exit.
14. Executor rejection policy
- AbortPolicy: The default blocking policy of java thread pool. This task is not executed, and a runtime exception is directly thrown. Remember to try.
catch, otherwise the program will exit directly. - DiscardPolicy: Directly discard, task not executed, empty method
- DiscardOldestPolicy: Discard a task of the head from the queue and execute this task again.
- CallerRunsPolicy: Execute this command in the thread calling execute, it will block
- User-defined rejection policy: implement RejectedExecutionHandler and define your own policy pattern
15、CachedThreadPool 、 FixedThreadPool、SingleThreadPool
- newSingleThreadExecutor: Create a single-threaded thread pool, which will only use a unique worker thread to execute tasks, ensuring that all tasks are executed in the specified order (FIFO, LIFO, priority).
Applicable scenarios: few tasks and no concurrent execution is required - newCachedThreadPool: Create a cacheable thread pool. If the thread pool length exceeds the processing needs, you can flexibly recycle idle threads. If there is no recycle, create a new thread.
When there is no task to be executed, it is in an idle state. The thread in an idle state will not be destroyed immediately (it will be cached). Only when the idle time exceeds a period of time (default is 60s), the thread pool will destroy the thread (equivalent to clearing outdated cache). After the new task arrives, the thread pool will first let the cached thread (idle state) execute the task. If there are no available threads (no idle threads), a new thread will be created.
Applicable scenarios: Task processing speed > Submit task speed, tasks that take less time (avoid unlimited new threads) - newFixedThreadPool: Create a fixed-length thread pool that can control the maximum number of threads concurrency, and the excess threads will wait in the queue.
- newScheduledThreadPool: Create a fixed-length thread pool that supports timed and periodic task execution
16、CopyOnWriteArrayList
CopyOnWriteArrayList: Lock when writing. When adding an element, copy the original container, copy a new container, and then write it in the new container. After writing, point the reference of the original container to the new container. When reading, read the data of the old container, so you can read concurrently, but this is a weak consistency strategy.
Usage scenario: CopyOnWriteArrayList is suitable for use in scenarios where read operations are much larger than write operations, such as cache.
17、AQS
- AQS uses an int member variable to represent the synchronization state, and the built-in FIFO queue is used to complete the queuing of the acquisition resource thread.
private volatile int state;//Share variables, use volatile to modify to ensure thread visibility
- 2 synchronization methods: exclusive and shared. Exclusive types such as ReentrantLock, shared types such as Semaphore, CountDownLatch, combined types such as ReentrantReadWriteLock
- The status of the node
CANCELLED, with a value of 1, indicating that the current thread is cancelled;
SIGNAL, with a value of -1, indicating that the threads contained in the successor node of the current node need to be run, that is, unpark;
CONDITION, the value is -2, which means that the current node is waiting for condition, that is, in the condition queue;
PROPAGATE, the value is -3, indicating that the subsequent acquireShared can be executed in the current scenario;
A value of 0 means that the current node is in the sync queue, waiting to acquire the lock. - Template method pattern
protected boolean tryAcquire(int arg): Exclusively obtain the synchronization status, try to obtain, and successfully return true, otherwise false
protected boolean tryRelease(int arg): Exclusively releases the synchronization state, and other threads waiting will have the opportunity to obtain the synchronization state at this time;
protected int tryAcquireShared(int arg): Shared obtains the synchronization status, and the return value is greater than or equal to 0, which means the acquisition is successful; otherwise, the acquisition fails;
protected boolean tryReleaseShared(int arg): Shared release synchronous state, success is true, failure is false
AQS maintains a shared resource state, and uses built-in FIFO to complete the queuing of resource threads. The queue consists of Node nodes one by one. Each Node node maintains a prev reference and next reference, pointing to its own predecessor and successor nodes respectively. Double-ended bidirectional link list. - Exclusive: Optimistic concurrency strategy
acquire
a. First tryAcquire gets the synchronization status, and if successful, it will return directly; otherwise, it will enter the next link;
b. If a thread fails to obtain the synchronization state, it constructs a node and joins the synchronization queue. This process must ensure thread safety;
c. The thread joining the node in the queue enters the spin state. If it is a second node (that is, the front-drive node is the header node), you have the opportunity to try to obtain the synchronization state; otherwise, when the state of the front-drive node is SIGNAL, the thread can rest with peace of mind and enter the blocking state until it is interrupted or awakened by the front-drive node.
release
The synchronization state of release is relatively simple. You need to find the successor node of the head node to wake up. If the successor node is empty or is in the CANCEL state, traverse from back to front to find a normal node and wake up its corresponding thread. - Shared:
Shared to get the synchronous state. The method of synchronous state tryAcquireShared returns the value of int.
a. When the return value is greater than 0, it means that the synchronization state is successfully obtained, and there is still a remaining synchronization state for other threads to obtain;
b. When the return value is equal to 0, it means that the synchronization status is successfully obtained, but no synchronization status is available;
c. When the return value is less than 0, it means that the synchronization status has failed to be obtained. - AQS implements fair locks and non-fair locks
In unfair locks, threads that try to acquire the lock and have not yet entered the waiting queue will compete with threads that are waiting for the head node of the queue. In fair lock, when acquiring the lock, isFirst(current) judgment is added. Only when the waiting queue is empty or the current thread is the header node of the waiting queue can you try to acquire the lock.
The cornerstone of Java concurrency package-AQS detailed explanation
18. Blocking queue in Java
7 blocking queues. They are
ArrayBlockingQueue: A bounded blocking queue composed of an array structure.
LinkedBlockingQueue: A bounded blocking queue composed of linked list structure.
PriorityBlockingQueue: An unbounded blocking queue that supports priority sorting.
DelayQueue: An unbounded blocking queue implemented using priority queues.
SynchronousQueue: A blocking queue that does not store elements.
LinkedTransferQueue: An unbounded blocking queue composed of linked list structure.
LinkedBlockingDeque: A bidirectional blocking queue composed of linked list structure.
Add elements
BlockingQueue in Java inherits from the Queue interface. The BlockingQueue interface provides 3 methods to add elements.
add: Add element to the queue, add success returns true, because the capacity is full and the addition fails to add, an IllegalStateException will be thrown
offer: add element to the queue, return true after adding success, return false after adding failure
put: Add elements to the queue. If the capacity is full, it will block until the capacity is not full.
Delete method
3 ways to delete
poll: Delete the queue header element, and return null if the queue is empty. Otherwise, return the element.
remove: Find the corresponding element based on the object and delete it. Return true if deleted successfully, otherwise return false
take: Delete the head element of the queue. If the queue is empty, block until the queue has elements and delete it.
19、condition
The main understanding of the source code of Condition is to understand the waiting queue. The waiting queue can be analogous to the synchronization queue, and the waiting queue is simpler than the synchronization queue, because the waiting queue is a one-way queue and the synchronization queue is a two-way queue.
Java condition usage and points
20、DelayQueue
Each element in the queue has an expiration time, and the queue is a priority queue. When obtaining elements from the queue, only the expired elements will be out of the queue.
Study on the principle of delayqueue for concurrent queue-unbounded blocking delay queue
21. Fork/Join Framework
The Fork/Join framework is a framework provided by Java 7 for parallel execution of tasks. It is a framework that divides large tasks into several small tasks, and finally summarizes the results of each small task and obtains the results of large tasks. The Fork/Join framework needs to accomplish two things:
1. Task segmentation: First of all, the Fork/Join framework needs to divide large tasks into small enough subtasks. If the subtask is relatively large, the subtasks must be further divided.
2. Execute tasks and merge results: the divided subtasks are placed in the double-ended queue, and then several startup threads obtain task execution from the double-ended queue. The results of the execution of the subtask are placed in another queue. A thread is started to retrieve data from the queue, and then merged the data.
In Java's Fork/Join framework, use two classes to complete the above operations
:To use the Fork/Join framework, we first need to create a ForkJoin task. This class provides a mechanism for executing forks and joins in tasks. Generally speaking, we do not need to directly integrate the ForkJoinTask class, we only need to inherit its subclass. The Fork/Join framework provides two subclasses:
: Used for tasks that do not return results
: Used for tasks with return results
:ForkJoinTask needs to be executed through ForkJoinPool
The subtasks split by the task will be added to the double-ended queue maintained by the current worker thread and enter the head of the queue. When there is no task in a queue of a worker thread, it will randomly obtain a task from the tail of the queue of other worker threads (work theft algorithm).
The implementation principle of Fork/Join framework
ForkJoinPool consists of ForkJoinTask array and ForkJoinWorkerThread array. ForkJoinTask array is responsible for submitting the stored program to ForkJoinPool, and ForkJoinWorkerThread is responsible for performing this
21. Atomic operation class
Under the package, it can be divided into four types of atom update classes: atom update basic type, atom update array type, atom update reference and atom update attributes.
- Atomic update basic type
Update the basic types using atomic method, including 3 classes in total:
AtomicBoolean: Atomic updates boolean variables
AtomicInteger: Atomic update integer variables
AtomicLong: Atomic updates long integer variables - Atomic update array
Update an element in the array through atoms, and there are 3 classes in total:
AtomicIntegerArray: Atomically updates an element of an integer array
AtomicLongArray: Atomic updates an element of a long array
AtomicReferenceArray: Atomic updates an element of a reference type array
Common methods used by AtomicIntegerArray are:
int addAndSet(int i, int delta): adds the input value atomically to the element in the array with index i
boolean compareAndSet(int i, int expect, int update): If the current value is equal to the expected value, the value indexed as i in the array is updated atomically as the update value - Atomic update reference type
AtomicReference: Atomic update reference type
AtomicReferenceFieldUpdater: Atomic update field in reference type
AtomicMarkableReference: Atomic updates the reference type with marker bits. - Atomic update field class
If you need to atomically update a certain field of a certain class, you need to use the atomically update field class. You can use the following classes:
AtomicIntegerFieldUpdater: Atomic update integer field
AtomicLongFieldUpdater: Atomic updates long integer fields
AtomicStampedReference: Atomic updates the reference type with a version number.
To atomically update a field, two steps are required:
Each time you have to use newUpdater to create an updater, and you need to set the fields of the class you want to update
The fields (properties) of the update class must be public volatile
22. Synchronous Barrier CyclicBarrier
CyclicBarrier literally means a barrier that can be recycled (Cyclic). What it needs to do is to make a group of threads block when they reach a barrier (also called a synchronization point). The barrier will not open until the last thread reaches the barrier, and all threads intercepted by the barrier will continue to work. The default constructor of CyclicBarrier is CyclicBarrier(int parties), whose parameters represent the number of threads blocked by the barrier. Each thread calls the await method to tell CyclicBarrier that I have reached the barrier, and then the current thread is blocked.
23.** The difference between CyclicBarrier and CountDownLatch**
CountDownLatch's counter can only be used once. The CyclicBarrier counter can be reset using the reset() method. Therefore, CyclicBarrier can handle more complex business scenarios. For example, if a calculation error occurs, you can reset the counter and let the threads execute it again.
CyclicBarrier also provides other useful methods, such as the getNumberWaiting method that can get the number of threads blocked by CyclicBarrier. The isBroken method is used to know whether the blocking thread is interrupted. For example, the following code will return true after execution.
24、Semaphore
Semaphore is used to control the number of threads that access specific resources at the same time. It coordinates each thread to ensure the reasonable use of public resources.
Semaphore can be used for traffic control, especially for application scenarios with limited public resources, such as database connections. If there is a requirement to read data from tens of thousands of files, because they are all IO-intensive tasks, we can start concurrent readings of dozens of threads, but if we read memory, it needs to be stored in the database, and the number of connections to the database is only 10. At this time, we must control that only ten threads obtain the database connection and save data at the same time, otherwise an error will be reported and the database connection cannot be obtained. At this time, we can use Semaphore to do flow control, the code is as follows:
Semaphore that controls the number of concurrent threads
25. Deadlock and solve the deadlock
Four necessary conditions for deadlock generation
Mutual Exclusion Conditions: Resources are exclusive and exclusive. Processes use resources mutually exclusively, that is, a resource can only be used by one process at any time. If other processes apply for one resource and the resource is occupied by another process, the applicant will wait until the resource is released by the occupier.
Inalienable conditions: The resources obtained by the process will not be forcibly deprived by other processes before they are used up, but can only be released by the resource resources of the process that obtains the resource.
Request and hold conditions: Each time the process applies for a part of the resources it needs, it continues to occupy the allocated resources while applying for new resources.
Loop waiting conditions: When a deadlock occurs, there must be a process waiting queue {P1,P2,…,Pn}, where P1 waits for the resources occupied by P2, P2 waits for the resources occupied by P3,…,Pn waits for the resources occupied by P1, forming a process waiting loop. The resources occupied by each process in the loop are applied by another, that is, the resources occupied by the previous process occupying the next process affectionately.
Solve deadlocks
First, deadlock prevention means not allowing the above four conditions to be established at the same time.
Second, rationally allocate resources.
The third is to use the banker algorithm. If the remaining amount of resource operating system requested by the process can be satisfied, then it will be allocated.
26. Communication methods between processes
- Pipe: Pipe is a half-duplex communication method, data can only flow in one-way and can only be used between processes with a kinship. The relationship between a process usually refers to the father-son process relationship.
- Named pipe: A famous pipe is also a half-duplex communication method, but it allows communication between unrelated processes.
- Semophore: Semophore is a counter that can be used to control access to shared resources by multiple processes. It often serves as a lock mechanism to prevent a process from accessing a shared resource when other processes are accessing the resource. Therefore, it is mainly used as a means of synchronization between processes and between different threads within the same process.
- Message queue: A message queue is a linked list of messages, stored in the kernel and identified by a message queue identifier. Message queues overcome the disadvantages of low signal transmission information, pipelines can only carry unformatted byte streams, and buffer size limited.
- Signal (sinal): A signal is a relatively complex communication method used to notify the receiving process that an event has occurred.
- Shared memory: Shared memory is to map a piece of memory that can be accessed by other processes. This shared memory is created by one process, but can be accessed by multiple processes. Shared memory is the fastest IPC method, and it is specially designed for other inter-process communication methods to operate inefficiently. It is often used in conjunction with other communication mechanisms, such as semaphores, to achieve synchronization and communication between processes.
- Socket: Socket is also an inter-process communication mechanism. Unlike other communication mechanisms, it can be used for process communication between different machines.
27. Interrupt
The function of interrupt() is to interrupt the thread.
This thread is allowed to interrupt itself; when other threads call the interrupt() method of this thread, the permission will be checked through checkAccess(). This may throw a SecurityException exception.
If the thread is in a blocking state: calling wait(), wait(long) or wait(long, int) of the thread will make it into a waiting (blocking) state, or calling join(), join(long), join(long, int), sleep(long), sleep(long, int) of the thread will also make it into a blocking state. If the thread calls its interrupt() method when it is blocking, its "interrupt state" will be cleared and an InterruptedException will be received. For example, a thread enters a blocking state through wait(), and the thread is interrupted by interrupt(); calling interrupt() will immediately set the thread's interrupt flag to "true", but since the thread is in a blocking state, the "interrupt flag" will be immediately cleared to "false", and an InterruptedException will be generated.
If the thread is blocked in a Selector selector, then when it is interrupted by interrupt(); the thread's interrupt flag is set to true and it will be returned immediately from the selection operation.
If it does not belong to the situation mentioned above, then when the thread is interrupted through interrupt(), its interrupt flag will be set to "true".
Interrupting a "terminated thread" will not cause any action.
- Terminates a thread in a "blocking state"
Usually, we terminate a thread in a "blocking state" by "interrupting".
When the thread enters a blocking state due to being called sleep(), wait(), join() and other methods; if the interrupt() of the thread is called at this time, the interrupt mark of the thread is set to true. Since it is in a blocking state, the interrupt flag will be cleared and an InterruptedException exception is generated. Putting InterruptedException until it is appropriate can terminate the thread. - Terminates a thread in "running state"
28. The difference between interrupted() and isInterrupted()
Finally, let’s talk about interrupted() and isInterrupted().
Both interrupted() and isInterrupted() can be used to detect "interrupt flags" of objects.
The difference is that in addition to returning the interrupt flag, interrupted() also clears the interrupt flag (i.e., set the interrupt flag to false); while isInterrupted() only returns the interrupt flag.
interrupt() and thread termination method