preface

A thread pool, hence its name, is a pool of threads, or in more academic terms, a collection of thread resources. Why did the concept of a thread pool come into being? Think before we are need of thread, direct themselves to create a manually, and execution of the tasks we have no matter, the thread will be our task to perform asynchronous a tool or carrier, we don’t have too much focus on this thread for a system or its own life cycle environmental impact, and only focus on the result of the multi-threaded tasks to complete the output, Then the goal is achieved, but the issues of thread resource maintenance and monitoring are really ignored. With the use of a large number of multithreaded resources in large systems, the neglect of attention, maintenance and management of multithreading has gradually expanded its impact on resource occupancy and low performance, which has aroused people’s thinking.

The creation and destruction of multithreading occupies a large proportion in the life cycle of multithreading, which actually occupies resources and performance. If threads are used to perform simple tasks, and the maintenance cost of threads itself has exceeded the benefits of task execution, it is not worth the loss, so the thread pool is generated. Through the use of thread pool, the life cycle of threads can be controlled, and threads can be easily acquired and reused, avoiding the frequent creation and destruction of threads to bring additional performance overhead, which is probably the background and original intention of the introduction of thread pool.

One, multi-threaded creation method

Create Thread class by inheriting Thread class

1. Implementation steps

Define a subclass that inherits Thread and override its run() method.

Create an instance of Thread subclass, that is, create a Thread object;

Call the start() method of the thread object to start the thread.

2. Core code

`class SomeThead extends Thraad { public void run() { //do something here

}

}

public static void main(String[] args){ SomeThread oneThread = new SomeThread(); // Start the thread onethread.start (); } `

1.2. Implement the Runnable interface to create thread classes

1. Implementation steps

Define an implementation class for the Runnable interface and override its run() method.

Create an instance of the Runnable implementation class and use it as the target object for Thread, which is the actual Thread object.

2. Core code

class SomeRunnable implements Runnable { public void run() { //do something here } } Runnable oneRunnable = new SomeRunnable(); Thread oneThread = new Thread(oneRunnable); oneThread.start();

1.3. Create threads with Callable and Future

1. Implementation steps

Create an implementation class for the Callable interface that implements the Call () method as the thread body and has a return value.

Create an instance of the Callable implementation class that wraps the Callable object with the FutrueTask class. The FutureTask encapsulates the return value of the Callable object’s call() method

Create and start a new Thread using the FutureTask object as the target of the Thread object

Call the Get () method of the FutureTask object to get the return value after the child thread completes execution.

2. Core code

‘//1. Create the Callable interface implementation class, Implements Callable {@override public Integer Call () throws Exception {int I = 0; for(; i<10; i++) { System.out.println(Thread.currentThread().getName()+” “+i); } return i; }

public static void main(String[] args) { //2. Create an instance of Callable implementation class SomeCallable01 CTT = new SomeCallable01(); FutureTask<Integer> ft = new FutureTask<>(CTT); FutureTask<>(CTT); For (int I = 0; i < 21; I ++) {system.out.println (thread.currentThread ().getName()+" I "); If (I ==20)// create the ft thread {//4. Create and start a new Thread using FutureTask as the target of Thread object. New Thread(ft," Thread with return value FutureTask").start(); }} // the ft thread ends with the return value try {//5. Call the Get () method of the FutureTask object to get the return value after the child thread completes execution. System.out.println(" return value of child thread: "+ft.get()); // The get() method blocks and does not return} catch (InterruptedException e) {e.printstackTrace (); } catch (ExecutionException e) { e.printStackTrace(); }}Copy the code

} `

2. Differences in the way threads are created

1. Create multiple threads by inheriting Thread

1) advantage

If you need access to the currentThread, use this instead of thread.currentthread ().

2) disadvantages

Thread classes already inherit from Thread, so they cannot inherit from other parent classes. (Limitations of single inheritance)

When creating multiple threads, each task that has member variables does not share them. Static is required to share them

2. Create multiple threads by implementing the Runnable class

1) advantage

The limitation of single inheritance is avoided. Multiple threads can share a target object, which is ideal for multi-threading the same resource.

2) disadvantages

Complex, accessing threads must use thread.currentThread () and return no value.

3. Create multiple threads by implementing the Callable interface

1) advantage

It has a return value, avoids the limitations of single inheritance, and multiple threads can share a target object, which is ideal for multi-threading the same resource.

2) disadvantages

More complex, accessing threads must use the thread.currentThread () method

4. Difference between Runnable and Callable

1) The Callable method is call(), and the Runnable method is run().

2) Callable tasks can return values after execution, while Runnable tasks cannot return values.

3) The call method can throw an exception, but the run method cannot.

4) Run the Callable task to get a Future object that represents the result of the asynchronous calculation. It provides a way to check that a calculation is complete, wait for it to complete, and retrieve the results of the calculation. The Future object can be used to know the execution status of the task, cancel the execution of the task, and obtain the execution result future.get().

Three, multi-threaded scheduling

3.1 scheduling strategy

Time slice: Threads are scheduled in a time slice rotation mode. Preemption: Threads with higher priorities preempt cpus

3.2 Java scheduling method

1) For threads of the same priority to form a first-in, first-out queue (first-come, first-served), time slice policy is used

2) For high priorities, preemptive scheduling policies are used

3.3. Thread priority

Rating:

MAX_PRIORITY:10

MIN_PRIORITY:1

NORM_PRIORITY:5

Methods:

‘getPriority(): Returns the thread priority

SetPriority (int newPriority): Changes the priority of a thread

Remark:

A higher priority thread preempts the CPU execution of a lower priority thread. But on a probabilistic basis, threads with higher priority are more likely to be executed. This does not mean that low-priority threads execute only after high-priority threads finish executing.

Fourth, multi-threaded state management

4.1. Thread sleep

1) overview

If we need to suspend the currently executing Thread for a while and block, we can call Thread’s sleep method.

2) Thread sleep method

To hibernate the executing thread for the specified number of milliseconds:

Sleep (long millis) sleeps the executing thread for the specified number of milliseconds plus the specified number of nanoseconds:

Sleep (Long Millis, int Nanos)

3) Code implementation

Sleep is a static method, and it is best not to call it with an instance object of Thread because it always sleeps with the currently running Thread, not the calling Thread object, and it only works with the running Thread object.

Public class SynTest {public static void main(String[] args) {new Thread(new CountDown(),” CountDown “).start(); }}

class CountDown implements Runnable{ int time = 10; public void run() { while (true) { if(time>=0){ System.out.println(Thread.currentThread().getName() + “:” + time–); try { Thread.sleep(1000); // Sleep for 1 second} catch (InterruptedException e) {e.printstackTrace (); }}}}} ‘

4) remarks

Java thread scheduling is the core of Java multithreading. Only good scheduling can give full play to the performance of the system and improve the execution efficiency of the program. However, no matter how programmers write schedules, they can only affect the order of thread execution to the maximum extent, but cannot achieve precise control. After using the sleep method, the Thread will enter the blocked state, and only when the sleep time ends, it will re-enter the ready state, and the ready state will enter the running state, which is controlled by the system, so it is impossible to accurately interfere with it. Therefore, if Thread. Sleep (1000) is called to make the Thread sleep for 1 second, It might be more than 1 second.

4.2. Thread yield

1) overview

The yield() method is similar to the sleep() method in that it is also a static method provided by the Thread class. It can also suspend the currently executing Thread, freeing CPU resources for another Thread. Unlike the sleep() method, however, it does not go into the blocking state, but into the ready state. The yield() method simply pauses the current thread and re-enters the ready thread pool, allowing the system’s thread scheduler to re-schedule it. It is entirely possible that when a thread calls the yield() method, the thread scheduler will re-schedule it for execution.

In fact, when a thread suspends with yield(), ready threads with the same or higher priority than the current thread are more likely to get the chance to execute. Just maybe, of course, because we can’t precisely interfere with the CPU scheduling threads.

2) Code implementation

Public class Test1 {public static void main(String[] args) throws InterruptedException {new MyThread(" low ", 1).start(); New MyThread(" intermediate ", 5).start(); New MyThread(" advanced ", 10).start(); } } class MyThread extends Thread { public MyThread(String name, int pro) { super(name); // Set the thread name this.setPriority(pro); } @override public void run() {for (int I = 0; i < 30; I ++) {system.out.println (this.getName() + "thread" + I + "! ); if (i % 5 == 0) Thread.yield(); }}}Copy the code

3) The difference between sleep and yield

① After suspending the current thread, the sleep method will enter the blocking state, and only when the sleep time is up, it will enter the ready state. When the yield method is called, it goes directly to the ready state, so it is possible to get into the ready state and then be scheduled to the run state.

② The sleep method declaration throws InterruptedException, so call the sleep method to catch the exception or display the declaration to throw it. The yield method does not declare to throw a task exception.

③ Sleep methods are more portable than yield methods, and usually do not rely on yield to control the execution of concurrent threads.

4.3 thread merge –join

1) overview

Thread merging means combining threads from several parallel threads into a single Thread. When a Thread must wait for another Thread to complete its execution, the Thread class provides a join method to do this. Note that this method is not static.

In short:

When thread B executes thread A’s.join () method, thread B waits until thread A finishes executing. Joins can be used to temporarily join thread execution.

2) Thread merging method

It has three overloaded methods:

The current thread waits for it to join the thread and wait for the thread to terminate.

void join()

The maximum time the current thread waits for this thread to terminate is millis milliseconds.

If the thread does not complete within millis time, the current thread enters the ready state and waits for the CPU to schedule again

void join(long millis)

The maximum time to wait for this thread to terminate is Millis milliseconds + nanos

A nanosecond. If the thread does not complete within millis time, the current thread enters the ready state and waits for the CPU to schedule again

void join(long millis,int nanos)

3) Code implementation

public static void main(String[] args) throws InterruptedException { yieldDemo ms = new yieldDemo(); T1 = new Thread(ms); t1 = new Thread(ms); Threadt2 = new threadt2 (ms, 1); Threadt3 = new Thread(ms, 1); t1.start(); t1.join(); t2.start(); t3.start(); System.out.println(" main thread "); }` Thread t = new Thread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } r = 10; }); t.start(); // let the main thread block and wait for t to finish before continuing. // Remove the line with the result of 0, plus the result of 10. log.info("r:{}", r); [main] INFO thread.TestJoin -r :10Copy the code

4.4. Set the priority of the thread

1) overview

Each thread has a priority attribute when it executes, and threads with higher priority get more execution opportunities, while threads with lower priority get less execution opportunities. Like thread sleep, thread priority still does not guarantee thread execution order. However, threads with higher priority are more likely to acquire CPU resources, and threads with lower priority are not deprived of execution.

By default, each thread has the same priority as the parent thread that created it, and by default, the main thread has normal priority.

2) Priority method is involved

The Thread class provides setPriority(int newPriority) and getPriority() methods to set and return the priority of a specified Thread. The setPriority method takes an integer ranging from 1 to ·0. You can also use the three static constants provided by the Thread class:

MAX_PRIORITY =10 MIN_PRIORITY =1 NORM_PRIORITY =5

3) Code implementation

Public class Test1 {public static void main(String[] args) throws InterruptedException {new MyThread(" high ", 10).start(); New MyThread(" low ", 1).start(); } } class MyThread extends Thread { public MyThread(String name,int pro) { super(name); // Set the thread name setPriority(pro); } @override public void run() {for (int I = 0; i < 100; I ++) {system.out.println (this.getName() + "thread" + I + "! ); }}}Copy the code

4) remarks

Although Java provides 10 priority levels, these priority levels require operating system support. Different operating systems have different priorities and do not correspond well to Java’s 10 priorities. The three static constants MAX_PRIORITY, MIN_PRIORITY, and NORM_PRIORITY should be used to set priorities for maximum portability.

4.5 background (daemon) threads

1) overview

Daemons are used less often, but not useless; for example, JVM threads for garbage collection, memory management, and so on are daemons. There is also in the database application, the use of the database connection pool, connection pool itself also contains a lot of background threads, monitoring the number of connections, timeout, status and so on.

By default, a Java process must wait for all threads to finish before terminating. There is a special thread called a daemon thread that forces termination even if it has not finished executing when all non-daemons have finished.

2) Methods involved

Call the thread object’s method setDaemon(true) to set it as a daemon thread.

Mark this thread as a daemon thread or a user thread. The Java virtual machine exits when all running threads are daemons. This method must be called before starting the thread. The method first calls the thread’s checkAccess method, taking no arguments. This may throw a SecurityException (in the current thread).

Public final void setDaemon(Boolean on) Parameter: on – Marks this thread as a daemon thread if true. Throws: IllegalThreadStateException – if this thread is active. SecurityException – If the current thread cannot modify the thread.

3) The purpose of daemon threads

Daemon threads are usually used to perform background tasks, such as playing background music while your application is running, automatic syntax checking, automatic saving in the text editor, and so on.

Java garbage collection is also a daemon thread. The nice thing about daemons is that you don’t have to worry about ending them. For example, if you want to play background music while your application is running, if you set the thread that plays background music as a non-daemon thread, you will not only exit the main thread, but also notify the thread that plays background music to exit when the user requests to exit. This is not required if you set it to a daemon thread.

4.6. Stop the thread

1) overview

Thread. Stop (), Thread. Suspend, Thread, resume, Runtime. RunFinalizersOnExit these terminated threads running method has been abandoned, their use is extremely unsafe.

The correct way to stop a thread is:

First: execute the run method normally, and then terminate.

Second: control loop conditions and judge condition identifiers to terminate the thread.

2) Implementation code examples

class MyThread extends Thread { int i=0; boolean next=true; @Override public void run() { while (next) { if(i==10) next=false; i++; System.out.println(i); }}}

4.7. Thread Interrupts

1) What is an interrupt?

Interrupt is only a cooperative mechanism, Java does not add any syntax to interrupt, interrupt process completely need programmers to achieve;

Each thread object has an identifier that indicates whether the thread is interrupted; If the flag bit is true, it is interrupted; if the flag bit is false, it is not interrupted.

Set the thread’s identity bit to true by calling the interrupt method on the thread object; It can be called from another thread, or it can be called from its own thread.

Interrupt flag: Whether the thread is interrupted, true indicates that it is interrupted, false indicates that it is not interrupted

2) Methods involved

() method:

Gets the thread’s interrupt flag (checked for each thread object called) without modifying the thread’s interrupt flag

Interrupt () method:

Interrupts this thread (which thread object is called is which thread object). If the thread to be interrupted is blocked (sleep, Wait, join), its interrupted status is cleared and an exception (InterruptedException) is thrown. This method does not actually stop the thread, but sets its interrupt state to “stop”, the thread will continue to run, as to how to stop the thread, still depends on our own to stop, this method only sets the thread state to “stop”, that is, true.

When a normal thread is interrupted, the thread is not actually interrupted, but the thread is marked true for interruption.

Interrupted () method:

Checks if the current thread is interrupted, in conjunction with the interrupt() method above. The thread’s interrupted status will be cleared by this method, that is, if this method is successfully called twice in a row, the second time

The call will return false (unless the current thread is interrupted again after the first call and before the second call).

That is: clear the interrupt flag after the call that is false if it gets true after the call (uncommon)

4.8. Threads are blocked

Thread blocking can be divided into several types. The definition of blocking at the operating system level and the Java level may differ, but in general, threads can be blocked in several ways:

1) BIO blocking, that is, using a blocking IO stream

2) Sleep (long time) allows the thread to sleep and enter the blocking state

3) the thread calling the method a.jin () blocks and waits for thread A to resume running

4) Sychronized or ReentrantLock causes the thread to block without acquiring the lock

5) Calling wait() after acquiring the lock also blocks the thread

6) locksupport.park () blocks the thread

Summary of thread core methods

5.1 Corresponding relationship between six thread states and methods

5.2 Summary of thread core methods

1) Core methods in the Thread class

2) Thread-related methods in Object

conclusion

Recently many people are in the interview, I sorted out a: Java multithreading information, Spring series family bucket (1187 pages of documentation), Java systematic information: (including 2021 latest Java core knowledge points, interview topics and 20 years of summary of the Internet real questions, e-books, etc.), friends in need can pay attention to the public number [procedures Yuan Xiao Wan] can obtain.