当前位置: 首页 > news >正文

温州58同城怎么做网站惠州seo网站排名

温州58同城怎么做网站,惠州seo网站排名,wordpress git升级,seo项目是什么目录 LockSupport与线程中断 线程中断机制 什么是中断机制? 与中断相关的3个API 如何停止中断运行中的线程? 当前线程的中断标识为true,是不是线程就会立刻停止? 如何理解静态方法Thread.interrupted() LockSupport是什么…

目录

LockSupport与线程中断

线程中断机制

什么是中断机制?

与中断相关的3个API

如何停止中断运行中的线程?

当前线程的中断标识为true,是不是线程就会立刻停止?

如何理解静态方法Thread.interrupted()

LockSupport是什么

线程等待和唤醒机制

3种让线程等待唤醒的方法

Object类中的wait()和notify()方法实现线程的等待和唤醒

Condition接口中的await()后signal()方法实现线程的等待和唤醒

上述两个对象Object和Condition使用的限制条件

LockSupport类中的park()等待和unpack()唤醒

总结


LockSupport与线程中断

线程中断机制

什么是中断机制?

首先,一个线程不应该由其他线程强制中断或停止,而是应该由线程自己自行停止,自己来决定自己的命运(所以,Thread的stop()、suspend()、resume()都已经废弃了)

其次,在Java中没有办法立即停止一条线程,然而停止线程又显得那么重要(比如需要取消一个耗时/错误操作)。因此,Java提供了一种用于停止线程的协商机制——中断,也即中断标识协商机制

中断只是一种协作协商机制,Java没有给中断增加任何语法,中断的过程完成完全要求程序员自己实现。若要中断一个线程,需要手动调用该线程的interrupt()方法,该方法也仅仅是将线程对象的中断标识设成true,接着按自己的需要,写代码不断监测当前线程的标识位,如果为true,表示别的线程请求这条线程中断,此时究竟该做什么需要自己写代码实现。

每个线程对象中都有一个中断标识位,用于表示线程是否被中断:该标识位为true标识中断,为false表示未中断。通过调用线程对象的interrupt方法将该线程的标识位设为true,可以在别的线程中带调用,也可以在自己的线程中调用。

与中断相关的3个API
  • public void interrupt():设置线程的中断状态为true,发起一个协商而不会立刻停止线程
  • public static boolean isInterrupted():通过检查中断标识位判断线程是否被中断并清除当前中断状态(返回当前线程的中断状态+重置中断状态为false)
  • public boolean isInterrupted():通过检查中断标识位判断当前线程是否被中断
如何停止中断运行中的线程?
  • 通过volatile变量实现(线程间的可见性)
  • 通过AtomicBoolean实现

执行结果如下图:

  • 通过Thread类自带的中断API实例方法实现 在需要中断的线程中不断监听中断状态,一旦发生中断,就执行相应的中断处理业务逻辑stop线程
    • interrupt() 中断线程

我们可以看到interrupt0()是一个native方法

除非线程正在中断(始终允许),否则将带调用此线程的checkAccess()方法(可能还会导致抛出SecurityException)

public class InterruptDemo {static volatile boolean isStop = false;public static void main(String[] args) {Thread tA = new Thread(() -> {while (true) {if (isStop) {System.out.printf(Thread.currentThread().getName() + " isStop 被修改为true!");break;}System.out.println("-------------------->");}}, "tA");tA.start();try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {isStop = true;}, "B").start();}
}

执行结果如下图:

public class InterruptDemo {static AtomicBoolean atomicBoolean = new AtomicBoolean(false);public static void main(String[] args) {Thread tA = new Thread(() -> {while (true) {if (atomicBoolean.get()) {System.out.printf(Thread.currentThread().getName() + " atomicBoolean 被修改为true!");break;}System.out.println("-------------------->");}}, "tA");tA.start();try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {atomicBoolean.set(true);}, "B").start();}
}
package com.aqin.juc;import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;/*** @Description* @Author aqin1012 AQin.* @Date 10/9/23 11:29 AM* @Version 1.0*/
public class InterruptDemo {public static void main(String[] args) {Thread tA = new Thread(() -> {while (true) {if (Thread.currentThread().isInterrupted()) {System.out.printf(Thread.currentThread().getName() + " isInterrupted() 被修改为true!程序停止!");break;}System.out.println("-------------------->");}}, "tA");tA.start();try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {tA.interrupt();}, "B").start();}
}

执行效果如下图:

当前线程的中断标识为true,是不是线程就会立刻停止?

不会,具体来说,对一个线程,调用interrupt()时,如果线程处于正常活动状态,那么会将该线程的中断标志设置为true(仅此而已),被设置中断标志的线程将继续正常运行,不受影响。所以,interrupt()并不是真正的中断线程,需要被调用的线程自己进行配合才行。如果线程处于被阻塞状态(如sleep、wait、join等状态),在别的线程中调用当前线程对象的interrupt()方法时,那么线程将会立即退出被阻塞状态,并抛出一个InterruptedException异常。

如何理解静态方法Thread.interrupted()

这个方法是判断线程是否中断并清除当前中断状态的,简单来说就是“复位”。

主要做了两件事:

  1. 返回当前线程的中断状态,测试当前线程是否已经被中断
  2. 将当前线程的中断状态清零并重新设置为false,清除线程的中断状态

那么问题来了,这个静态方法interrupted()跟实例方法isInterrupted()有什么区别呢?

我们举个简单的例子对比下执行结果

静态方法interrupted()

执行结果如下:

实例方法isInterrupted()

执行结果如下

来看它俩的源码对比

可以看到其实它们调用的是同一个方法,只不过,在对于是否需要清理这个参数的传递上,静态方法传递的是true,而实例方法传递的是false,简单来讲就是多了一步“复位”操作。因此,才会出现上面两段示例代码执行的结果不一致,在当前线程未执行中断方法interrupt()时,当前线程的中断标识位本身就是初始值false,因此连续调用两次静态方法或者实例方法的执行结果都是false;当当前线程执行了中断方法interrupt()时,第一次调用静态方法和实例方法的返回值同样都是true,但是此时静态方法多做了一步“复位”操作,把当前线程的中断标识位重置回了初始值false,而实例方法则没有这步操作,因此,当第二次调用时,实例方法的示例中当前线程的中断标识位仍然是true,因此仍然返回true,而静态方法的示例代码中当前线程的中断标识位已经被重置回了false,于是就返回了false。

LockSupport是什么

LockSupport是java.util.concurrent.locks中的一个类,用于创建锁和其他同步类的基本线程阻塞原语

线程等待和唤醒机制

3种让线程等待唤醒的方法
  1. 使用Object中的wait()方法让线程等待,使用notify()方法唤醒线程
  2. 使用JUC包中的Condition的await()方法让线程等待,使用signal()方法唤醒线程
  3. 使用LockSupport类中的park()和unpark()方法阻塞当前线程以及唤醒指定被阻塞的线程
Object类中的wait()和notify()方法实现线程的等待和唤醒

示例代码:

public static void main(String[] args) {Object objectLock = new Object();new Thread(() -> {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}synchronized (objectLock) {System.out.println(Thread.currentThread().getName() + " 进入--->");try {objectLock.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " 被唤醒^ ^");}}, "A").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {synchronized (objectLock) {objectLock.notify();}System.out.println(Thread.currentThread().getName() + " 发出唤醒通知( ̄∇ ̄)/");}, "B").start();
}

执行结果如下:

问题:

  • 必须要先持有锁,否则会报错

  • 必须先wait()再notify(),否则会卡死

Condition接口中的await()后signal()方法实现线程的等待和唤醒

示例代码:

public static void main(String[] args) {Lock lock = new ReentrantLock();Condition condition = lock.newCondition();new Thread(() -> {try { TimeUnit.SECONDS.sleep(1); } catch ( InterruptedException e) { e.printStackTrace();}lock.lock();System.out.println(Thread.currentThread().getName() + " 进入--->");try {condition.await();} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}System.out.println(Thread.currentThread().getName() + " 被唤醒^ ^");}, "A").start();try { TimeUnit.SECONDS.sleep(1); } catch ( InterruptedException e) { e.printStackTrace();}new Thread(() -> {lock.lock();try {condition.signal();} finally {lock.unlock();}System.out.println(Thread.currentThread().getName() + " 发出唤醒通知( ̄∇ ̄)/");}, "B").start();}

执行结果如下:

问题:

  • 必须要先持有锁,否则会报错

在lock、unlock对里面才能正确调用condition中线程等待和唤醒的方法。

  • 必须先await()再signal(),否则会卡死

上述两个对象Object和Condition使用的限制条件
  • 线程先要获得并持有锁,必须在锁块(synchronized/lock)中
  • 必须要先等待后唤醒,线程才能够被唤醒
LockSupport类中的park()等待和unpack()唤醒

LockSupport类使用了一种名为Permit(许可)的概念来做到阻塞和唤醒线程的功能,每一个线程都有一个Permit(许可),但与Semaphore不同的是,许可的累加上限是1(最多一个许可)。

使用示例:

public static void main(String[] args) {Thread A = new Thread(() -> {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " 进入--->");LockSupport.park();System.out.println(Thread.currentThread().getName() + " 被唤醒^ ^");}, "A");A.start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {LockSupport.unpark(A);System.out.println(Thread.currentThread().getName() + " 发出唤醒通知( ̄∇ ̄)/");}, "B").start();
}

执行结果如下:

可以看到,使用LockSupport进行线程阻塞/唤醒不需要在锁对块(synchronized/lock)中,所以上面Object类和Condition接口的第一个问题解决了,然后我们看看第二个问题:加锁/解锁的先后顺序。

如上图可以看出,park()和unpack()执行的先后顺序不会影响结果。

总结

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。

LockSupport是一个线程阻塞工具,所有的方法都是静态方法,可以让线程在任意位置阻塞,阻塞后也有对应的唤醒方法,归根结底,LockSupport调用的是Unsafe中的native代码。

LockSupport提供park()和unpark()方法实现阻塞线程和解除线程阻塞的过程,每个使用LockSupport的线程都一个Permit(许可)与LockSupport相关联,每一个线程都都一个相关的Permit,并且最多一个,重复调用unpark()也不会积累Permit。

换句话讲,线程阻塞需要消耗凭证,并且这个凭证最多1个

当调用park()方法时:

  • 如果有Permit,会消耗这个Permit,然后正常退出
  • 如果没有Permit,会阻塞当前线程等待获取凭证

当调用unpark()方法时:

  • 会增加一个Permit
  • 调用多次也只会有一个Permit(不累加)

最后,我们思考2个问题:

  1. 为什么LockSupport提供park()和unpark()方法可以突破Object和Condition的调用先后顺序的限制? 因为调用unpark()会获得1个Permit,之后再调用park()会消耗这个Permit,park()和unpark()方法的执行顺序不会影响线程的唤醒,即便先发放了Permit仍然不会阻塞线程。
  2. 唤醒两次(调用两次park()方法)后阻塞两次(调用两次unpark)方法),会发生什么情况? 线程会被阻塞,因为Permit不会累加,即使调用了两次unpark(),仍然只会有一个Permit,后面接着的调用两次park(),在调用第一次park()时,就会把这个Permit消耗掉,第二次调用时就没有Permit了,因而会被阻塞。

搞定( ̄∇ ̄)/🎉🎉🎉~~~~~~~~~~

http://www.tj-hxxt.cn/news/11729.html

相关文章:

  • 网站面板爱站网域名查询
  • 有哪些做软件的网站网站alexa排名查询
  • 上海青浦做网站凡科建站多少钱
  • 做网站的费用入什么科目千锋教育和黑马哪个好
  • 网站怎么做下载连接seo研究协会网
  • 邢台网站制作地方运营培训班学费大概多少
  • 哈尔滨房地产网站建设舆情通
  • 网站建设 软件开发广州网站运营专业乐云seo
  • win系统和mac那个做网站好今日油价92汽油价格
  • 毕业设计做网站怎么样介绍产品的营销推文
  • 介绍做网站的标题企业营销策划有限公司
  • iis部署网站提示建设中湖南网站建设工作室
  • 直播网站开发源码软件开发公司简介
  • 合肥网站制作前3名的站长域名查询工具
  • 引用网站资料怎么注明沪深300指数
  • asp网站怎么做404页面跳转百度开户怎么开
  • 12306网站 谁做的nba实力榜最新排名
  • 网店设计公司网站seo完整seo优化方案
  • 自己建网站需要备案吗成都网站推广经理
  • 网站制作建实体店引流推广方法
  • 网站项目开发流程及规范影视网站怎么优化关键词排名
  • 企业网站改版建议网络推广网站大全
  • 鹤壁做网站价格运营培训班学费大概多少
  • 凡客是什么品牌上海专业seo排名优化
  • 厦门做外贸网站深圳网站建设推广优化公司
  • 顺的网站建设咨询重庆森林经典台词梁朝伟
  • 专业团队怎样建设网站最彻底的手机优化软件
  • b2c网站比较重庆专业做网站公司
  • 网站 服务器 带宽 估算 网站流量网络营销方案设计
  • 平面设计师灵感网站网络销售面试问题有哪些