多線程管理-主動或被動停止線程
- 線程被動地暫停和終止
– 依靠別的線程來拯救自己
– 沒有及時釋放資源
– 在生產者/消費者示例中,線程wait的時候,需要靠別的線程來notify,只有notify了,其他線程才能從wait的狀態解脫出來,這樣線程就是被動的暫停和終止,這種情況很危險,例如線程打開了一個文件,或者拿着某一個鎖對象,一旦進入wait狀態,鎖或者文件不能夠及時的釋放資源,可以使用定期監測共享變量,當共享變量變爲某種狀態時,先釋放資源,再暫停或者終止。 - 線程主動暫停和終止
– 定期檢測共享變量
– 如果需要暫停或者終止,先釋放資源,再主動動作
– 暫停:Thread.sleep(),休眠
– 終止:run方法結束,線程終止
主動、被動停止線程示例:
interrupted()是Thread類的方法,用來測試當前線程是否收到一個INTERRUPT的信號。如果收到,該方法返回true,否則返回false。
package interrupt;
/**
* @ClassName:InterruptTest
* @Description:
* @author: Torey
*/
public class InterruptTest {
public static void main(String[] args) throws InterruptedException {
//
TestThread1 t1 = new TestThread1();
TestThread2 t2 = new TestThread2();
t1.start();
t2.start();
//讓線程運行一會後中斷
Thread.sleep(2000);
//interrupt 是讓線程中斷
//被動停止
t1.interrupt();
//主動停止
t2.flag=false;
System.out.println("main thread is exiting");
}
}
/**
* 被動的停止
*/
class TestThread1 extends Thread{
@Override
public void run() {
//判斷標誌,當本線程被被別人interrupt後,JVM會被本線程設置interrupted標記
//interrupted()是Thread類的方法,用來測試當前線程是否收到一個interrupt的信號。
// 如果收到,該方法返回true,否則返回false.
//這裏是被動的停止線程
while (!interrupted()) {
System.out.println("test thread1 is running");
try{
Thread.sleep(1000);
}catch (Exception ex){
ex.printStackTrace();
break;
}
}
}
}
/**
* 主動的停止
*/
class TestThread2 extends Thread{
public volatile boolean flag=true;
@Override
public void run(){
//判斷標誌,當本線程被別人interrupt後,JVM被本線程設置interrupted標記
//這裏是主動停止線程
while (flag) {
System.out.println("test thread2 is running");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("test thread2 is exitting");
}
}
多線程管理-鎖,守護線程
- 多線程死鎖
– 每個線程互相持有別人需要的鎖(哲學家吃麪問題)
– 預防死鎖,對資源進行等級排序 - 守護(後臺)線程
– 普通線程的結束,是run方法運行結束
– 守護線程的結束,是run方法運行結束,或main函數結束
– 守護線程永遠不要訪問資源,如文件或數據庫等 - 線程查看工具jvisualvm
死鎖實例:
package deadlock;
import java.util.concurrent.TimeUnit;
/**
* @ClassName:ThreadDemo5
* @Description:死鎖測試
* @author: Torey
*/
public class ThreadDemo5 {
public static Integer r1=1;
public static Integer r2=2;
public static void main(String[] args){
TestThread51 t1 = new TestThread51();
t1.start();
TestThread52 t2 = new TestThread52();
t2.start();
}
}
class TestThread51 extends Thread{
@Override
public void run(){
//避免死鎖,就需要等資源進行等級排序加鎖
// synchronized (ThreadDemo5.r1){
synchronized (ThreadDemo5.r2){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
// synchronized (ThreadDemo5.r1){
synchronized (ThreadDemo5.r2){
System.out.println("TestThread51 is running");
}
}
}
}
class TestThread52 extends Thread{
@Override
public void run(){
synchronized (ThreadDemo5.r1){
try {
//TimeUnit是JDK5 引入的新類,位於java.util.concurrent包中
//它提供了時間單位和一些時間轉換、計時和延遲等函數
//這裏是睡眠3秒
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (ThreadDemo5.r2){
System.out.println("TestThread52 is running");
}
}
}
}
命令輸入jvisualvm,查看是否有死鎖
守護線程
守護線程的結束,是run方法運行結束,或main函數結束
package daemon;
/**
* @ClassName:ThreadDemo4
* @Description:
* @author: Torey
*/
public class ThreadDemo4 {
public static void main(String[] args) throws InterruptedException {
TestThread4 t = new TestThread4();
//setDaemon(true) 設置守護線程
t.setDaemon(true);
t.start();
Thread.sleep(2000);
System.out.println("main thread is exiting");
}
}
class TestThread4 extends Thread{
@Override
public void run(){
while (true){
System.out.println("TestThread4 is running");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}