Java提升——多線程(四)等待、喚醒、線程中斷、優先級和守護線程

等待&喚醒

關於Object類提供的wait、notify、notifyAll三個方法:ide

wait():讓當前線程處於等待(阻塞)狀態,直到其餘線程調用該同步監視器的notify(),notifyAll()方法來喚醒該線程,進入就緒狀態。wait()會釋放對當前線程的同步監視器的鎖定this

—>無時間參數的wait:一直等到,直到其餘線程通知喚醒spa

—>帶時間參數的wait:等待指定時間後自動喚醒。線程

notify():喚醒在此同步監視器上等待的單個線程。若監視器上有不少個線程等待,則任意喚醒一個。code

notifyAll:喚醒在此同步監視器上等待的全部線程。對象

wait&notify示例:blog

class Thread2 extends Thread{
    public Thread2(String name) {
        super(name);  }
    @Override  public void run(){
        synchronized (this) {
            System.out.println(Thread.currentThread().getName()+" call notify()");  //喚醒當前的wait線程  notify();  }
    }
}
public class WaitTest {
    public static void main(String[] args) throws InterruptedException {
        Thread2 t = new Thread2("t2");  synchronized (t) {
            //啓動線程  t.start();  //讓線程等待  System.out.println("wait");  t.wait();  }
    }
}

主線程main經過實例化獲取線程t,隨後經過synchronized(t)獲取t對象的同步鎖,以後調用start方法啓動線程t。get

主線程main經過執行t.wait()釋放t的同步鎖,進入了「等待(阻塞)狀態」,等待t對象經過notify喚醒「當前對象上等待的線程」,也就是主線程。同步

wait和notify之間依賴於同步鎖,而同步鎖是對象持有的,所以這幾個方法屬於Object。
it

線程中斷

中斷方式:

—>終止處於「阻塞狀態」的線程

當線程調用了yield、join、sleep等方法進入阻塞狀態,若此時調用線程的interrupt()方法,將線程中斷標記設置爲true,處於阻塞狀態,中斷標記將被清除同時產生一個IntertuptedException異常,將異常放在適合的位置將會終止線程。

@Override public void run() {
    try {
        while (true){
            //to-do  }
    }catch(InterruptedException ie){
        // 產生InterruptedException異常,退出while循環,線程終止  }
}

—>終止處於「運行狀態」的線程

1)經過「中斷標記」中斷線程

@Override public void run() {
    while (!isInterruped()){
        //.......  }
}
isInterrupted是判斷線程中的中斷標記是否爲true

2)經過「額外標記」中斷線程

private volatile boolean flag = true; @Override public void run() {
    while (flag){
        //.......  }
}
優先級

Java中的優先級範圍是1-10:

MAX_PRIORITY:10

MIN_PRIORITY:1

NOR_PRIORITY:5(默認)

能夠經過setPriority()改變線程的優先級,高優先級的線程將會得到更多執行的機會。

守護線程

Java的線程分爲兩種:用戶線程和守護線程(後臺線程),能夠用isDaemon()方法來區別:若是返回false則爲用戶線程,不然爲守護線程,JVM的垃圾回收線程就是典型的守護線程(後臺線程)

後臺線程的特徵:若是前臺線程都死亡,後臺線程會自動死亡

能夠用setDaemon(true)將指定線程設定爲後臺線程。

class Daemon extends Thread{
    //後臺線程的設定與普通線程並無任何區別  @Override  public void run() {
        for (int i = 0; i < 10 ; i++) {
            System.out.print(Thread.currentThread().getName()+"-"+i);  }
    }
}
public class Test {
    public static void main(String[] args) {
        Daemon d = new Daemon();  //將線程設置爲守護線程  d.setDaemon(true);  //啓動線程  d.start();  for (int i = 0; i < 10 ; i++) {
            System.out.println(Thread.currentThread().getName()+" "+i+" ");  }
        //線程執行到此,前臺線程(main)執行結束  //後臺線程也跟着結束  }
}

主線程默認爲前臺線程。前臺線程建立的子線程默認爲前臺線程,後臺線程建立的子線程默認爲後臺線程。

前臺死亡以後JVM會通知後臺後臺線程死亡,並且須要必定時間。要將某個線程設置爲後臺線程必定要在該線程啓動以前設置

也就是說setDaemon(true)要在start以前,不然將會報IllegalThreadStateException異常。

相關文章
相關標籤/搜索