1. start() Would call run() Method , Why do we still choose to use start() Method to open the thread
start()
Methods call most of the timestart0() Of native Method
, It can start the life cycle of a thread correctly .
run()
Method is just a common method
2. A thread calls twice start() What happens to the method ? Why?
- It throws an exception
The reason is thatThread t = new Thread()
when The state of the thread isNEW
Yesstart()
after , The thread will check the current thread state , IfNEW
Just run the thread , The thread state is changed toRunnable
, When the second executionstart()
When the thread status is found Not for NEW Will throw an exception
3. How many ways to implement threads ?
- Make clear your position
From a different point of view , There will be different answers
I think it’s all implementation in essence Runnable And inheritance Thread - Give me an example
Thread pool Worker It’s essentially thread safe Runnable
The core thread of the thread pool It’s using Thread.start() Open
Support the return value of FutureTask It’s using Future One of the interface extensions Runnable
Timing task TimerTask Also a Runnable
4. How to stop a thread
-
use
interrupt
To request
interrupt It’s not forcing the responder to respond immediately , It can participate in the business logic of the responder , Does not interrupt the responder’s original business logic , Ensure data security -
Use interrupt It needs cooperation -> Use api Or abnormal response
2.1 Ordinary scenes
Thread.interrupt
+Thread.currentThread().isInterrupted()
public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { int i = 0; while (!Thread.currentThread().isInterrupted() && i < Integer.MAX_VALUE / 2) { if (i % 10000 == 0) { System.out.println(i); } i++; } } }; Thread thread = new Thread(runnable); thread.start(); try { Thread.sleep(2000); // zhege sleep Just let the thread run into the loop } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); }
2.2 with sleep() The situation of
Capture exceptiontry { int i = 0; while (!Thread.currentThread().isInterrupted() && i <= 300) { if (i % 100 == 0) { System.out.println(i); } i++; } Thread.sleep(1000); // sleep Outside the loop } catch (InterruptedException e) { e.printStackTrace(); }
2.3 Every cycle sleep()
Note that the interrupt flag will automatically clear after throwing an exception , Be careful try catch The scope of processing oftry { int i = 0; while (!Thread.currentThread().isInterrupted() && i <= 300) { if (i % 100 == 0) { System.out.println(i); } i++; Thread.sleep(1000); // sleep Inside the loop /* If try-catch Put it inside , Only one interrupt will be responded to , The next loop will reset the interrupt flag bit , If you want to use try-catch, And let the program respond to the interrupt and exit the loop , Need to use a big try Wrap the loop . */ } } catch (InterruptedException e) { e.printStackTrace(); }
2.4 Best practices for interruptions in multi tier calls
- Priority is given to throw interrupt exceptions , It’s forced on run Method
- volite Can’t handle a long time blocking situation , It’s easy to fall into a hole
- When the interrupt cannot be delivered , Prevent interrupts from being reset , Set the interrupt again
catch
It was interrupted again +isInterrupted()
@Override public void run() { while (true) { if (Thread.currentThread().isInterrupted()) { System.out.println(" The inner method has been broken , The outer method also needs to be interrupted , Out of the loop "); break; } System.out.println("go"); reInterrupt(); } } /** * In a child thread sleep() After the interruption , Then manually set the interrupt flag position to true * */ private void reInterrupt() { try { Thread.sleep(2000); } catch (InterruptedException e) { System.out.println(" Print log "); Thread.currentThread().interrupt(); e.printStackTrace(); } }
- Other blocks that can be interrupted
5. How to deal with non interruptible blocking
unfortunately , There is no universal solution ,
But you can give two examples of scenarios :
ReentrantLock.lockInterruptibly()
Can respond to interruptions- Inherit
Thread rewrite interrupt()
Handle IO Interruption of reading and writing
6. Six states of thread
- The twist of the State
- A special case
7. Handwritten producers, consumers
8. Alternate printing by program 0~100 Number of numbers
9. Why? wait() Need to be in sync block , and sleep Unwanted
- Code specification perspective :
wait()
Method andnotify()
It needs to be used together , Introduce synchronous code blocks to make notify() Strictly stay wait() After execution .
Multithreading requires such a mandatory specification - wait() The implementation of is lock level operation
wait() Will release the caller’s lock , If not explicitly specified, it isthis.wait()
,
Each object maintains amonitor
Used to save lock information
So in the synchronization code block, uselock.wait()
Make all lock objects available wait(), Allow code to schedule with multiple locks wait() Methodfinal static Object lock = new Object(); sychronized(lock){ lock.wait() }
- It can be used Thread.wait() Do you ?
Do not use , It will cause hidden danger ,Thread At the time of design, we have completed an implementation , Thread execution completed , Automatic execution Thread.notify(),
The execution time of a thread is uncontrollable , implicit Thread.notifyj() It can lead to unexpected results
10. notify() and notifyAll() The difference between
11. join period , What state is the thread in
thread.join()
The equivalent code of :
synchronized (thread) {
thread.wait(); //
}
because thread Design time to achieve , Once the thread is finished , perform thead.notifyAll().
thread.join()
It also implicitly realizes the main thread waiting thread The logic to run after it’s done
Main thread call thread.join()
thread yes running state main yes waiting state
12. The difference between the guardian thread and the user thread
The guard thread serves the user thread ,JVM The program is terminated when no user thread is detected .
Even if there are Guardian threads , There is no user thread ,JVM You will think that there is no need for the guardian thread to exist
13. How to catch the exception thrown by the child thread in the main thread
- Realization
Thread.UncaughtExceptionHandler
Generate your own exception catcher
@Slf4j
public class MyUnCaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
log.info("Thread : {}, thrown a Exception : {} ", t.getName(), e.getMessage());
}
}
-
Register your own exception catcher with the main thread
Thread.setDefaultUncaughtExceptionHandler(new MyUnCaughtExceptionHandler());
-
Supplementary knowledge :
14. The disadvantages of multithreading
Scheduling of threads
- Context switch -> Lock competition 、 A lot of IO operation
What is context switching ? Context is some register related operation of the operating system ,
A context switch has the following activities :- Suspend a thread
- Store the state of a thread somewhere in memory , The information stored is
- Which instruction does the thread execute , Where is the position of the command
- Program counter
- Cache overhead
CPU and There are multiple levels of cache between the memory to coordinate the speed difference , Caching is often used to improve the execution efficiency of applications , Such as for loop
Frequent context switching can lead to cache invalidation
Thread collaboration
- Memory synchronization
volatile Prohibit command rearrangement , Let optimization fail
Each thread may no longer maintain its own cache , To synchronize the main memory , Cost of access