zoukankan      html  css  js  c++  java
  • Java-线程等待、唤醒与中断

    一、sleep() 与 wait()

    两者都会让当前线程进入等待状态。唤醒后都需要等待 CPU 资源,不一定会立即执行。若在等待期间被调用此线程的的 interrupt() 方法,将会产生 InterruptedException 异常。

    wait() 是 Object 类的方法,会释放对象锁,并让出 CPU 资源。只能在 synchronized 下使用,使用 notify() 或 notiftAll() 唤醒。

    // 线程工厂,这里主要用来设置线程名字
    ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
    // 创建线程池
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(6, 6, 0L,
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1024),
            namedThreadFactory,
            new ThreadPoolExecutor.AbortPolicy());
    
    Object object = new Object();
    threadPool.execute(() -> {
        try {
            synchronized (object) {
                object.wait();
                System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAA");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
    
    threadPool.execute(() -> {
        synchronized (object) {
            System.out.println("BBBBBBBBBBBBBBBBBBBBBBBBBBB");
            object.notify();
        }
    });
    View Code

    sleep() 是 Thread 类的静态方法,只会让出 CPU 资源。可以使低优先级的线程得到执行的机会。

    // 线程工厂,这里主要用来设置线程名字
    ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
    // 创建线程池
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(6, 6, 0L,
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1024),
            namedThreadFactory,
            new ThreadPoolExecutor.AbortPolicy());
    
    threadPool.execute(() -> {
        try {
            // 阻塞 1 秒
            Thread.sleep(1000);
            System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAA");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
    
    threadPool.execute(() -> {
        System.out.println("BBBBBBBBBBBBBBBBBBBBBBBBBBBB");
    });
    View Code

    两个示例都保证了 B 会在 A 之前被打印

      

    二、notify() 与 notifyAll()

    与 wait() 配合使用。两者都会唤醒其他线程,且会释放对象锁,不会阻塞当前线程。

    其中 notify() 只唤醒等待线程当中的一个,notifyAll() 会唤醒所有等待线程。

    notify() 是随机唤醒的,不同的 JDK 版本,在等待队列中唤醒的线程,其位置在等待队列中不同。

    JDK1.8 中 notify() 唤醒的是等待队列中的头节点,即等待时间最长的那个线程。

    唤醒的线程为同一个对象锁的线程。唤醒一个或所有,都只有一个线程会获取到锁对象。

    三、yield() 与 join()

    yield() 是 Thread 类的静态原生 (native) 方法,作用是让出 CPU 资源,不会阻塞当前线程,但可能让出 CPU 资源后,系统重新调度后又会选择给该线程 CPU 资源。使用场景比较少。

    join() 是Thread 类实例的方法,可以使得一个线程在另一个线程结束后再执行。当前运行的线程将进入到等待状态直到另一个线程执行完成。

    Thread t1 = new Thread(){
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
                System.out.println("A");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    
    Thread t2 = new Thread(){
        @Override
        public void run() {
            try {
                t1.join();
                System.out.println("B");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    
    t2.start();
    t1.start();
    View Code

    示例中保证了 A 在 B 之前被打印

    四、interrupt()

    中断等待状态的线程,并抛出异常。相关方法有三个。

    interrupt() 是 Thread 类实例的方法,给线程中断状态设置为 false,等线程进入到等待状态时就会被中断,并抛出异常

    isInterrupted() 是 Thread 类实例的方法,检测线程的中断状态

    interrupted() 是 Thread 类的静态方法,实质调用的是 currentThread().isInterrupted(true),作用是检测线程的中断状态,然后将状态设置为 true

    Thread t1 = new Thread() {
        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + "启动后的中断状态:" + Thread.currentThread().isInterrupted());
    
                Thread.currentThread().interrupt();
                System.out.println(Thread.currentThread().getName() + "interrupt()后的中断状态:" + Thread.currentThread().isInterrupted());
    
                System.out.println(Thread.currentThread().getName() + "isInterrupted()获取中断状态:" + Thread.interrupted());
                System.out.println(Thread.currentThread().getName() + "interrupted()后的中断状态:" + Thread.currentThread().isInterrupted());
    
                Thread.currentThread().interrupt();
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println(Thread.currentThread().getName() + "异常时中断状态:" + Thread.interrupted());
            }
        }
    };
    
    new Thread() {
        @Override
        public void run() {
            System.out.println(t1.getName() + "未启动时的中断状态:" + t1.isInterrupted());
            System.out.println("=======================================================");
            t1.start();
            try {
                t1.join();
                System.out.println("=======================================================");
                System.out.println(t1.getName() + "执行完时的中断状态:" + t1.isInterrupted());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }.start();
    View Code


    https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

  • 相关阅读:
    合同主体列表添加两条合同主体,返回合并支付页面,支付总弹"请选择合同主体",删除后,竟然还能支付(改合并支付页面的字段状态)
    (TODO:)下载图片,报错:warning: could not load any Objective-C class information from the dyld shared cache. This will significantly reduce the quality of type information available.
    GCD死锁 多线程
    iOS知识总结
    快速排序,冒泡排序,选择排序
    fight
    3D Touch
    Xcode 调试技巧
    右滑退出手势及隐藏导航栏存在的风险
    C语言-第5课
  • 原文地址:https://www.cnblogs.com/jhxxb/p/10864125.html
Copyright © 2011-2022 走看看