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异常。

相关文章
相关标签/搜索