一、復習
void interrupt()、boolean isInterrupted()、boolean interrupted() interrupt()方法只是為了做一個“中斷”的標記,而不會真的停止該執行緒、isInterrupted是回傳執行緒的中斷狀態、interrupted()方法也是一樣的,但是這是一個static方法,可以直接呼叫而且根據原始碼,是所在的執行緒的中斷狀態,而且如果結果為true,它會立即消除“中斷”狀態,
二、背景關系切換
定義:CPU會給各個執行緒分配時間片,當一個執行緒的時間片使用結束后,它會處于就緒狀態,此時CPU會切換到另外一個執行緒,這就是背景關系切換, 背景關系切換的時機有兩個:(1)執行緒使用完時間片完全處于就緒狀態時;(2)執行緒被中斷;
三、死鎖
定義:兩個或者兩個以上的執行緒,當他們進行爭奪資源用于執行的時候,形成一種互相等待的局面,就是死鎖,
1.死鎖產生的四個必要條件:
(1)互斥條件:執行緒對已經獲得的資源進行排他性使用,也就是資源被占用,只能由一個執行緒占用,如果其他執行緒想要獲得該資源,就必須等待,除非該執行緒釋放了資源, (2)請求并持有條件:一個執行緒占有了資源,并且還想要其他資源,但是此時其他資源被其他執行緒占用了,那么此時在等待資源釋放,并且并不會釋放自己已經持有的資源 (3)不可剝奪條件:一個執行緒占用了資源,直到它使用完才會釋放,在此期間如果由其他執行緒想要該資源,是不能搶占的 (4)環路等待條件,也就是有一個執行緒集合{t1,t2,t3,......tn},t1想要t2的資源,t2想要t3的資源......直到tn想要t1的資源,形成一個環路 舉個死鎖的例子
package com.ruigege.threadFoundation1;
public class DeadLockExample {
//創建資源
private static Object object1 = new Object();
private static Object object2 = new Object();
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(object1) {
System.out.println("執行緒1獲得了資源1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized(object2) {
System.out.println("執行緒1獲得了資源2");
}
}
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(object2) {
System.out.println("執行緒2獲得了資源2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized(object1) {
System.out.println("執行緒2獲得了資源1");
}
}
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
}

兩者互相等待上了,死鎖的四個條件都滿足了,形成了死鎖
2.如何避免死鎖
至少需要破壞一個必要條件,學過作業系統的小伙伴知道,目前只用請求并持有條件和環路等待條件是可以破壞的,上面的代碼稍微改動,把第二個執行緒的object1和object2,位置互換,也就是和執行緒1的順序一致,運行: 
四、守護執行緒
在Java中有兩種執行緒一種是用戶執行緒,一種是守護執行緒,我們使用的main函式就是一個用戶執行緒,垃圾回收器就是一個守護執行緒,守護執行緒的描述就是JVM的退出并不取決于守護執行緒是否還在運行,也就是說,當用戶執行緒結束的時候,退出JVM,此時是否有守護執行緒都無所謂,依然會退出,
1.創建一個守護執行緒
執行緒.setDaemon(true);
執行緒.start();
呼叫setDaemon方法即可,我們來測驗一下,上面描述的特性是否成立
package com.ruigege.threadFoundation1;
public class DaemonThreadTest {
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
//我們這里搞一個死回圈也就是讓子執行緒不停
}
}
});
thread1.setDaemon(true);
thread1.start();
System.out.println("主執行緒已經結束了,看一看后面還有沒有游標在動");
}
}

第一個沒設定為守護執行緒,可以看到雖然主執行緒已經結束了,但是子執行緒沒有結束,程式仍然在運行;第二個就是設定了,但是主執行緒一結束,守護執行緒也結束了,
linux命令 ps -ef | grep java 這個Linux命令代表什么 ps代表的是顯示某個行程;grep全稱為global regular expression print代表是查找的意思,它的后面可以接正則運算式,這個grep java就是代表查找出所有帶有java的行程然后顯示出來; |是管道符合,這里代表的意思就是前后兩個命令同時執行; ps后面跟一些引數,-e代表所有的行程;-f代表全稱執行緒,還有其他引數,百度了一下,-h : 不顯示標題;-l : 長格式-w : 寬輸出;a :顯示終端上的所有行程,包括其他用戶的行程;r :只顯示正在運行的行程;u :以用戶為主的格式來顯示程式狀況;x :顯示所有程式,不以終端機來區分,
總結:如果你想要主執行緒結束之后馬上退出JVM,那么就可以把子執行緒設定為守護執行緒,反之,就把子執行緒設定為用戶執行緒,
五、ThreadLocal決議
多執行緒訪問同一個共享物件的時候,往往會有并發問題,那么我們可以通過加鎖的方式來保證物件的內容統一,但是這種效率很低,于是Java的JDK提供了一個類ThreadLocal,該共享變數的作業原理是:一旦創建了一個共享變數之后,它會在每個執行緒中創建一個副本,用于本執行緒使用,實際操作的是自己執行緒獨有的副本,保證執行緒安全,不會和其他執行緒混淆 我們接下來舉個例子:
package com.ruigege.threadFoundation1;
public class ThreadLocalTest {
public static ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void printContentOfThreadLocal(ThreadLocal threadLocal) {
System.out.println(threadLocal.get());
threadLocal.remove();
}
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
threadLocal.set("共享變數1");
System.out.println("執行緒1的共享變數是:");
printContentOfThreadLocal(threadLocal);
System.out.println("執行緒1去除共享變數后的值為:" + threadLocal.get());
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
threadLocal.set("共享變數2");
System.out.println("執行緒2的共享變數是:");
printContentOfThreadLocal(threadLocal);
System.out.println("執行緒2去除共享變數后的值為:" + threadLocal.get());
}
});
thread1.start();
try {
Thread.sleep(100);
}catch(InterruptedException e) {
e.printStackTrace();
}
thread2.start();
}
}

第一個是把陳述句threadLocal.remove注釋掉的結果,第二個是沒有注釋的結果,
六、原始碼:
所在包:com.ruigege.ThreadFoundation1 https://github.com/ruigege66/ConcurrentJavaCSDN:https://blog.csdn.net/weixin_44630050 博客園:https://www.cnblogs.com/ruigege0000/ 歡迎關注微信公眾號:傅里葉變換,個人賬號,僅用于技術交流 
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/203922.html
標籤:其他
上一篇:elasticsearch7.6.2 -canal1.1.4集成
下一篇:Spring的簡單使用
