栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

多线程的中断和等待唤醒机制

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

多线程的中断和等待唤醒机制

文章目录
    • 线程的中断
      • 什么是中断 它意味着什么
        • 前提
        • 详细解释
      • 三个中断相关方法的解释
        • void interrupt
        • static boolean interrupted
        • boolean interrupted
      • 怎么响应中断停止线程
        • 通过volatitle变量实现
        • 原子变量操作 (他的值也是volatitle标识的)
        • 通过Thread类自带的中断api方法实现
      • 中断停止的坑
    • 线程的等待和唤醒
      • 三种机制
        • synchronized的wait和notify方法
        • Condition的await和signal方法
        • LockSupport类的park和unpark方法

线程的中断 什么是中断 它意味着什么 前提

首先,一个线程就不应该由其他线程来进行强制的中断或者停止,而是应该由线程自己自行停止.所以Thread类中的停止方法都已经被废弃了 不允许在调用了.
其次,既然在Java中没有办法立即停止一条线程,但是停止线程这个需求也是一个刚需,非常重要(比如取消掉耗时的操作),那Java怎么办呢? Java给大家提供了一种用于停止线程的机制 -中断.

详细解释

中断只是一种协作机制,Java没有给中断增加任何语法,中断的过程去由线程的设计者自己去实现.
若要中断一个线程,你需要手动的调用该线程的interrupt方法,该方法也仅仅是将线程对象的中断标识设成true;
接着你需要自己写代码不断地检测当前线程的标识位,如果为true,表示有线程要求你停止.完全由你自主决定怎么做(自己也可以对自己进行中断操作)

三个中断相关方法的解释 void interrupt

实例方法,仅仅是设置线程的中断状态为true,不会停止线程

static boolean interrupted

静态方法 Thread.interrupted() 他做了两件事

  • 返回当前线程的中断状态
  • 将当前线程的中断状态设置为false
boolean interrupted

实例方法 判断当前线程是否被中断

怎么响应中断停止线程 通过volatitle变量实现
static volatile boolean isStop = false;

    public static void main(String[] args) {
        new Thread(() -> {
            while (true) {
                if (isStop) {
                    System.out.println("线程终止");
                    break;
                }
                System.out.println("走走走");
            }
        }, "aa").start();
        try {
            TimeUnit.SECONDS.sleep(1L);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        new Thread(() -> {
            isStop = true;
        }, "555").start();


    }
原子变量操作 (他的值也是volatitle标识的)
static AtomicBoolean atomicBoolean = new AtomicBoolean(false);

    public static void main(String[] args) {
        new Thread(() -> {
            while (true) {
                if (atomicBoolean.get()) {
                    System.out.println("线程终止");
                    break;
                }
                System.out.println("走走走");
            }
        }, "aa").start();
        try {
            TimeUnit.SECONDS.sleep(1L);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        new Thread(() -> {
            atomicBoolean.set(true);
        }, "555").start();
    }
通过Thread类自带的中断api方法实现
Thread thread = new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("线程终止");
                    break;
                }
                System.out.println("走走走");
            }
        }, "aa");
        thread.start();
        try {
            TimeUnit.SECONDS.sleep(2L);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        new Thread(() -> {
            thread.interrupt();
        }, "555").start();
中断停止的坑

对线程发起中断时,如果此线程在调用Object类的wait() 、 wait(long)或wait(long, int)方法或join() 、 join(long) 、 join(long, int) int) 方法时被阻塞, sleep(long) , or sleep(long, int) , 这个类的方法,那么它的中断状态将被清除,它会收到一个InterruptedException 。

这个异常会导致中断状态被复位为false,导致收到中断信号的线程永远也无法停止 所以必须处理InterruptedException这个异常(通常就是在异常捕获里本线程在调用一下自己的中断方法)

    try {
        TimeUnit.SECONDS.sleep(1L);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
线程的等待和唤醒 三种机制 synchronized的wait和notify方法

来自于Object基类的本地方法 必须在synchronized修饰的方法或代码块中调用,否则会抛出IllegalMonitorStateException异常,所以他们是强绑定的关系.并且wait和notify方法顺序不能错误 否则会造成阻塞

static Object objectLock = new Object();
new Thread(() -> {
            synchronized (objectLock){
                try {
                    objectLock.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("被唤醒啦");
            }
        }, "aaa").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        new Thread(()->{
            synchronized (objectLock){
                objectLock.notify();
                System.out.println("发出来通知了");
            }
        }).start();
Condition的await和signal方法

juc包的类,也需要包裹在Lock类的lock和unlock代码块内,否则会抛出IllegalMonitorStateException异常,await和signal的调用顺序也不能反否则会一直阻塞

    static Lock lock = new ReentrantLock();

    static Condition condition = lock.newCondition();
	new Thread(() -> {
            lock.lock();
            try {
                System.out.println("come in");
                condition.await();
                System.out.println("被唤醒");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
        }, "aaa").start();

        new Thread(() -> {
            lock.lock();
            try {
                condition.signal();
                System.out.println("发出通知");
            } finally {
                lock.unlock();
            }
        }, "bbbb").start();
	
LockSupport类的park和unpark方法

优势是不需要给代码上锁,park和unpark方法的调用顺序可以是相反的不会阻塞

是因为他底层采用的是通行证的原理 有一个值只能为0或者1的标志位 先执行unpark相当于先发了通行证,后再去执行park的时候也不会阻塞,直接放行 通行证的值上限就是1 多次重复的unpark也不会增加上限

Thread t1 = new Thread(() -> {
            System.out.println("come in");
            LockSupport.park();
            System.out.println("被唤醒");
        }, "aaa");
        t1.start();
        new Thread(() -> {
            System.out.println("发出通知");
            LockSupport.unpark(t1);
        }, "ffffsf").start();
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1000473.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号