zoukankan      html  css  js  c++  java
  • Java提高——多线程(四)等待、唤醒、线程中断、优先级和守护线程

    等待&唤醒

    关于Object类提供的wait、notify、notifyAll三个方法:

    wait():让当前线程处于等待(阻塞)状态,直到其他线程调用该同步监视器的notify(),notifyAll()方法来唤醒该线程,进入就绪状态。wait()会释放对当前线程的同步监视器的锁定

    —>无时间参数的wait:一直等到,直到其他线程通知唤醒

    —>带时间参数的wait:等待指定时间后自动唤醒。

    notify():唤醒在此同步监视器上等待的单个线程。若监视器上有很多个线程等待,则任意唤醒一个。

    notifyAll:唤醒在此同步监视器上等待的所有线程。

    wait&notify示例:

    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。

    主线程main通过执行t.wait()释放t的同步锁,进入了“等待(阻塞)状态”,等待t对象通过notify唤醒“当前对象上等待的线程”,也就是主线程。

    wait和notify之间依赖于同步锁,而同步锁是对象持有的,因此这几个方法属于Object。

    线程中断

    中断方式:

    —>终止处于“阻塞状态”的线程

    当线程调用了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异常。

  • 相关阅读:
    hdu 3714
    sql 函数 DATEADD 使用
    mvc的IIS 配置问题 runAllManagedModulesForAllRequests 与 HtmlFileHandler
    移动端日历控件 mobiscroll 的简单使用、参数设置
    sql中判断是否存在某个对象
    SQLServer中的变量:局部变量,全局变量
    键盘对照表
    [PyQt]在Windows系统中安装Eric6
    [Python]使用QRCode生成彩色二维码
    [PyQt]PyQt5连接SQL Server数据库,并读取所有数据库名称
  • 原文地址:https://www.cnblogs.com/huangzhe1515023110/p/9276094.html
Copyright © 2011-2022 走看看