一:啟動線程的正确和錯誤方式
1.start()方法的執行流程
- 檢查線程狀态(隻有線程為0(new)狀态時才能啟動線程,否則會抛異常,運作中或已經結束的狀态均會抛異常)
- 加入線程組
- 調用start0()方法啟動線程
#注意:start()方法是synchronized修飾的,是以該方法是線程安全的
package threadcoreknowledge.startthread;
/**
* @author 小賢
* @PackageName:
* @ClassName:StartAndRunMethod
* @Description:
* @date 2022/1/3 22:20
*/
public class StartAndRunMethod {
public static void main(String[] args) {
Runnable runnable = () -> {
System.out.println(Thread.currentThread().getName());
};
runnable.run();//隻是單純的調用run方法
new Thread(runnable).start();//建立一個線程,經曆線程的各個生命周期
}
}
二:正确停止線程
1.原理:使用interrupt來通知,而不是強制
#Java沒有提供任何機制來安全地終止線程。但它提供了中斷( Interruption),這是一種協作機制
#使用interrupt來通知線程停止的原因是:【通知線程停止的通知方】是不了解【被要求停止線程】的内部機制,而【被要求停止線程】方是知道自己停止線程時所需要執行的業務,是以最終停止線程的決定權還是在【被要求停止線程】方,我們能做的就是通知他要停止線程。
2.正确停止線程的正确姿勢
`(1)子方法将中斷信号抛出,讓被請求停止線程方處理`
package threadcoreknowledge.stopthreads;
/**
* @author 小賢
* @PackageName:
* @ClassName:RightWayStopThreadInProd
* @Description:
* @date 2022/1/12 22:58
*/
public class RightWayStopThreadInProd implements Runnable {
@Override
public void run() {
while (true) {
System.out.println("線程開始執行任務");
try {
innerMethod();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("哎呀,發生錯誤了,趕緊記錄一下日志。");
break;
}
}
}
private void innerMethod() throws InterruptedException {
Thread.sleep(2000);
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new RightWayStopThreadInProd());
thread.start();
Thread.sleep(1000);
thread.interrupt();
}
}
`(2)子方法将中斷信号捕獲,捕獲處理完畢後将線程狀态再次設定為中斷狀态`
package threadcoreknowledge.stopthreads;
/**
* @author 小賢
* @PackageName:
* @ClassName:RightWayStopThreadInProd
* @Description:
* @date 2022/1/12 22:58
*/
public class RightWayStopThreadInProd2 implements Runnable {
@Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("線程被中斷,任務執行完畢");
break;
}
System.out.println("線程開始執行任務");
innerMethod();
}
}
private void innerMethod() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new RightWayStopThreadInProd2());
thread.start();
Thread.sleep(1000);
thread.interrupt();
}
}
(3)volatile并不是一個正确的停止線程的方案,因為如果一個線程長期處于阻塞的狀态,volatile并不能讓線程響應中斷信号
package threadcoreknowledge.stopthreads.volatiledemo;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
/**
* @author 小賢
* @PackageName:
* @ClassName:VolatileCantStopThread
* @Description:
* @date 2022/1/15 20:23
*/
public class VolatileCantStopThread {
/* * @Author 小賢
* @Description //生産者
* @Date 20:27 2022/1/15
* @Param
* @return
**/
class producer implements Runnable{
BlockingQueue blockingQueue;
public volatile boolean result = false;
public producer(BlockingQueue blockingQueue) {
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
try {
int num = 0;
while (num <= 100000 && !result) {
if (num % 100 == 0) {
System.out.println(num + "進入隊列");
blockingQueue.put(num);
Thread.sleep(10);
}
num++;
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("生産者線程結束");
}
}
}
/* * @Author 小賢
* @Description //消費者
* @Date 20:30 2022/1/15
* @Param
* @return
**/
class consumer {
BlockingQueue blockingQueue;
public consumer(BlockingQueue blockingQueue) {
this.blockingQueue = blockingQueue;
}
public boolean isTakeOver() {
if (Math.random() > 0.95) {
return false;
}
return true;
}
}
public static void main(String[] args) throws InterruptedException {
ArrayBlockingQueue queue = new ArrayBlockingQueue(10);
VolatileCantStopThread volatileCantStopThread = new VolatileCantStopThread();
producer producer = volatileCantStopThread.new producer(queue);
Thread thread = new Thread(producer);
thread.start();
Thread.sleep(1000);
consumer consumer = volatileCantStopThread.new consumer(queue);
while (consumer.isTakeOver()) {
System.out.println(queue.take() + "被消費了");
Thread.sleep(10);
}
System.out.println("消費者消費完畢");
producer.result = true;
}
}
3.java異常體系
- Throwable:是java異常體系的根類,他的兩個子孩子為:Error和Exception
- Error:通常是指程式出現了無法解決的錯誤,程式奔潰情況,如記憶體溢出等問題
- Exception:這個是我們日常用得比較多的,他分為RuntimeException(運作時異常),還有其他一些checkException(可預見異常)
#unCheckException(不可預見異常):Error和RuntimeException
#checkException:除unCheckException以外的異常
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiMGc902byZ2P2IWZ2YTY2EWN0ITN0IjNiRjMmRTYhlTOjFjZxImZlR2LcBza5QTcsJja2FXLp1ibj1ycvR3Lc5Wanlmcv9CXt92YucWbp9WYpRXdvRnL2A3Lc9CX6MHc0RHaiojIsJye.jpg)
如何正确停止線程
- 原理:用interrupt來請求線程停止而不是強制,好處是安全。因為被停止的線程可能需要處理一些資料再結束線程,貿然停掉線程可能會造成程式出錯。
- 想停止線程,要請求方、被停止方、子方法被調用方互相配合才行: a) 作為被停止方:每次循環中或者适時檢查中斷信号,并且在可能抛出InterrupedException的地方處理該中斷信号; b) 請求方:發出中斷信号; c) 子方法調用方(被線程調用的方法的作者)要注意:優先在方法層面抛出InterrupedException,或者檢查到中斷信号時,再次設定中斷狀态;
- stop/suspend已廢棄,volatile的boolean無法處理長時間阻塞的情況
怎樣處理不可響應中斷的阻塞
沒有特定的方法,需要具體情況分析,用特定的方法喚醒線程。