当前位置:网站首页>4、LockSupport与线程中断
4、LockSupport与线程中断
2022-06-11 12:07:00 【施小赞】
1、线程中断机制
1.1、一道面试题
如何停止、中断一个运行中的线程?

1.2、什么是中断?
首先
一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。
所以,Thread.stop, Thread.suspend, Thread.resume 都已经被废弃了。
其次
在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。
因此,Java提供了一种用于停止线程的机制——中断。
中断只是一种协作机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现。
若要中断一个线程,你需要手动调用该线程的 interrupt 方法, 该方法也仅仅是将线程对象的中断标识设成true ;
接着你需要自己写代码不断地检测当前线程的标识位,如果为true,表示别的线程要求这条线程中断,
此时究竟该做什么需要你自己写代码实现。
每个线程对象中都有一个标识,用于表示线程是否被中断;该标识位为true表示中断,为false表示未中断;
通过调用线程对象的interrupt方法将该线程的标识位设为true;可以在别的线程中调用,也可以在自己的线程中调用。
1.3、中断的相关API方法

public void interrupt() | 实例方法, 实例方法interrupt()仅仅是设置线程的中断状态为true,不会停止线程 |
public static boolean interrupted() | 静态方法,Thread.interrupted(); 判断线程是否被中断,并清除当前中断状态 这个方法做了两件事: 1 返回当前线程的中断状态 2 将当前线程的中断状态设为false
这个方法有点不好理解,因为连续调用两次的结果可能不一样 。 |
public boolean isInterrupted() | 实例方法, 判断当前线程是否被中断(通过检查中断标志位) |
1.4、面试题:如何使用中断标识停止线程?
在需要中断的线程中不断监听中断状态,
一旦发生中断,就执行相应的中断处理业务逻辑。
修改状态
停止程序的运行。。。
1.4.1、方法
通过一个volatile变量实现
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @auther zzyy
* @create 2021-03-03 18:20
*/
public class InterruptDemoCopy {
static volatile boolean isStop = false;
public static void main(String[] args) {
new Thread(() -> {
while (true) {
if (isStop) {
System.out.println("-----isStop = true,程序结束。");
break;
}
System.out.println("------hello isStop");
}
}, "t1").start();
//暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
isStop = true;
}, "t2").start();
}
}
返回结果:
------hello isStop
------hello isStop
------hello isStop
------hello isStop
------hello isStop
------hello isStop
-----isStop = true,程序结束。通过AtomicBoolean
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @auther zzyy
* @create 2021-03-03 18:20
*/
public class InterruptDemoCopy {
static AtomicBoolean atomicBoolean = new AtomicBoolean(false);
public static void main(String[] args) {
new Thread(() -> {
while(true)
{
if(atomicBoolean.get())
{
System.out.println("-----atomicBoolean.get() = true,程序结束。");
break;
}
System.out.println("------hello atomicBoolean");
}
},"t1").start();
//暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
new Thread(() -> {
atomicBoolean.set(true);
},"t2").start();
}
}
返回结果:
------hello atomicBoolean
------hello atomicBoolean
------hello atomicBoolean
------hello atomicBoolean
------hello atomicBoolean
------hello atomicBoolean
------hello atomicBoolean
-----atomicBoolean.get() = true,程序结束。通过Thread类自带的中断api方法实现
实例方法interrupt(),没有返回值
源码分析:

实例方法isInterrupted,返回布尔值
源码分析:

code
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @auther zzyy
* @create 2021-03-03 18:20
*/
public class InterruptDemoCopy {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("-----isInterrupted() = true,程序结束。");
break;
}
System.out.println("------hello Interrupt");
}
}, "t1");
t1.start();
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
new Thread(() -> {
t1.interrupt();//修改t1线程的中断标志位为true
},"t2").start();
}
}
返回结果:
------hello Interrupt
------hello Interrupt
------hello Interrupt
------hello Interrupt
------hello Interrupt
------hello Interrupt
-----isInterrupted() = true,程序结束。1.4.2、当前线程的中断标识为true,是不是就立刻停止?
说明:
具体来说,当对一个线程,调用 interrupt() 时:
① 如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true, 仅此而已 。
被设置中断标志的线程将继续正常运行,不受影响 。所以, interrupt() 并不能真正的中断线程,需要被调用的线程自己进行配合才行。
② 如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),在别的线程中调用当前线程对象的interrupt方法,
那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。
code1
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @auther zzyy
* @create 2021-03-03 18:20
*/
public class InterruptDemoCopy {
public static void main(String[] args) {
//中断为true后,并不是立刻stop程序
Thread t1 = new Thread(() -> {
for (int i = 1; i <= 300; i++) {
System.out.println("------i: " + i);
}
System.out.println("t1.interrupt()调用之后02: "+Thread.currentThread().isInterrupted());
}, "t1");
t1.start();
System.out.println("t1.interrupt()调用之前,t1线程的中断标识默认值: "+t1.isInterrupted());
try { TimeUnit.MILLISECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
//实例方法interrupt()仅仅是设置线程的中断状态位设置为true,不会停止线程
t1.interrupt();
//活动状态,t1线程还在执行中
System.out.println("t1.interrupt()调用之后01: "+t1.isInterrupted());
try { TimeUnit.MILLISECONDS.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
//非活动状态,t1线程不在执行中,已经结束执行了。
System.out.println("t1.interrupt()调用之后03: "+t1.isInterrupted());
}
}运行结果
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=61077:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/tools.jar:/Users/shishizan/2022-java/大厂JUC/代码/juc2021/target/classes:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter-web/2.4.3/spring-boot-starter-web-2.4.3.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter/2.4.3/spring-boot-starter-2.4.3.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter-logging/2.4.3/spring-boot-starter-logging-2.4.3.jar:/Users/shishizan/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/Users/shishizan/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/Users/shishizan/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.13.3/log4j-to-slf4j-2.13.3.jar:/Users/shishizan/.m2/repository/org/apache/logging/log4j/log4j-api/2.13.3/log4j-api-2.13.3.jar:/Users/shishizan/.m2/repository/org/slf4j/jul-to-slf4j/1.7.30/jul-to-slf4j-1.7.30.jar:/Users/shishizan/.m2/repository/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5.jar:/Users/shishizan/.m2/repository/org/yaml/snakeyaml/1.27/snakeyaml-1.27.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter-json/2.4.3/spring-boot-starter-json-2.4.3.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.11.4/jackson-databind-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.11.4/jackson-annotations-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.11.4/jackson-core-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.11.4/jackson-datatype-jdk8-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.11.4/jackson-datatype-jsr310-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.11.4/jackson-module-parameter-names-2.11.4.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/2.4.3/spring-boot-starter-tomcat-2.4.3.jar:/Users/shishizan/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/9.0.43/tomcat-embed-core-9.0.43.jar:/Users/shishizan/.m2/repository/org/glassfish/jakarta.el/3.0.3/jakarta.el-3.0.3.jar:/Users/shishizan/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.43/tomcat-embed-websocket-9.0.43.jar:/Users/shishizan/.m2/repository/org/springframework/spring-web/5.3.4/spring-web-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-beans/5.3.4/spring-beans-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-webmvc/5.3.4/spring-webmvc-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-aop/5.3.4/spring-aop-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-context/5.3.4/spring-context-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-expression/5.3.4/spring-expression-5.3.4.jar:/Users/shishizan/.m2/repository/org/openjdk/jol/jol-core/0.9/jol-core-0.9.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-devtools/2.4.3/spring-boot-devtools-2.4.3.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot/2.4.3/spring-boot-2.4.3.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.4.3/spring-boot-autoconfigure-2.4.3.jar:/Users/shishizan/.m2/repository/org/projectlombok/lombok/1.18.18/lombok-1.18.18.jar:/Users/shishizan/.m2/repository/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar:/Users/shishizan/.m2/repository/org/springframework/spring-core/5.3.4/spring-core-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-jcl/5.3.4/spring-jcl-5.3.4.jar com.atguigu.juc.interrupt.InterruptDemoCopy
t1.interrupt()调用之前,t1线程的中断标识默认值: false
------i: 1
------i: 2
------i: 3
------i: 4
------i: 5
------i: 6
------i: 7
------i: 8
------i: 9
------i: 10
------i: 11
------i: 12
------i: 13
。。。。。。
------i: 218
------i: 219
------i: 220
------i: 221
------i: 222
------i: 223
t1.interrupt()调用之后01: true
------i: 224
------i: 225
------i: 226
------i: 227
------i: 228
------i: 229
。。。。。。
------i: 298
------i: 299
------i: 300
t1.interrupt()调用之后02: true
t1.interrupt()调用之后03: false
Process finished with exit code 0code2
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @auther zzyy
* @create 2021-03-03 18:20
*/
public class InterruptDemoCopy {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("-----isInterrupted() = true,程序结束。");
break;
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();//??????? //线程的中断标志位为false,无法停下,需要再次掉interrupt()设置true
e.printStackTrace();
}
System.out.println("------hello Interrupt");
}
}, "t1");
t1.start();
try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
new Thread(() -> {
t1.interrupt();//修改t1线程的中断标志位为true
},"t2").start();
}
}
返回结果
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=63044:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/tools.jar:/Users/shishizan/2022-java/大厂JUC/代码/juc2021/target/classes:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter-web/2.4.3/spring-boot-starter-web-2.4.3.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter/2.4.3/spring-boot-starter-2.4.3.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter-logging/2.4.3/spring-boot-starter-logging-2.4.3.jar:/Users/shishizan/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/Users/shishizan/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/Users/shishizan/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.13.3/log4j-to-slf4j-2.13.3.jar:/Users/shishizan/.m2/repository/org/apache/logging/log4j/log4j-api/2.13.3/log4j-api-2.13.3.jar:/Users/shishizan/.m2/repository/org/slf4j/jul-to-slf4j/1.7.30/jul-to-slf4j-1.7.30.jar:/Users/shishizan/.m2/repository/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5.jar:/Users/shishizan/.m2/repository/org/yaml/snakeyaml/1.27/snakeyaml-1.27.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter-json/2.4.3/spring-boot-starter-json-2.4.3.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.11.4/jackson-databind-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.11.4/jackson-annotations-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.11.4/jackson-core-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.11.4/jackson-datatype-jdk8-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.11.4/jackson-datatype-jsr310-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.11.4/jackson-module-parameter-names-2.11.4.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/2.4.3/spring-boot-starter-tomcat-2.4.3.jar:/Users/shishizan/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/9.0.43/tomcat-embed-core-9.0.43.jar:/Users/shishizan/.m2/repository/org/glassfish/jakarta.el/3.0.3/jakarta.el-3.0.3.jar:/Users/shishizan/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.43/tomcat-embed-websocket-9.0.43.jar:/Users/shishizan/.m2/repository/org/springframework/spring-web/5.3.4/spring-web-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-beans/5.3.4/spring-beans-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-webmvc/5.3.4/spring-webmvc-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-aop/5.3.4/spring-aop-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-context/5.3.4/spring-context-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-expression/5.3.4/spring-expression-5.3.4.jar:/Users/shishizan/.m2/repository/org/openjdk/jol/jol-core/0.9/jol-core-0.9.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-devtools/2.4.3/spring-boot-devtools-2.4.3.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot/2.4.3/spring-boot-2.4.3.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.4.3/spring-boot-autoconfigure-2.4.3.jar:/Users/shishizan/.m2/repository/org/projectlombok/lombok/1.18.18/lombok-1.18.18.jar:/Users/shishizan/.m2/repository/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar:/Users/shishizan/.m2/repository/org/springframework/spring-core/5.3.4/spring-core-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-jcl/5.3.4/spring-jcl-5.3.4.jar com.atguigu.juc.interrupt.InterruptDemoCopy
------hello Interrupt
------hello Interrupt
------hello Interrupt
------hello Interrupt
------hello Interrupt
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.atguigu.juc.interrupt.InterruptDemoCopy.lambda$main$0(InterruptDemoCopy.java:20)
at java.lang.Thread.run(Thread.java:748)
------hello Interrupt
-----isInterrupted() = true,程序结束。
Process finished with exit code 0
结论:
sleep方法抛出InterruptedException后,中断标识也被清空置为false,我们在catch没有通过调用Thread.currentThread().interrupt();方法再次将中断表示置为true,这就导致无限循环了
小总结:
中断只是一种协同机制,修改中断标识位仅此而已,不是立刻stop打断
1.4.2、静态方法Thread.interrupted()
静态方法Thread.interrupted():
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @auther zzyy
* @create 2021-03-03 18:20
*/
public class InterruptDemoCopy {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() + "---" + Thread.interrupted());
System.out.println(Thread.currentThread().getName() + "---" + Thread.interrupted());
System.out.println("111111");
/* 作用是测试当前线程是否被中断(检查中断标志),返回一个 boolean 并清除中断状态,
* 第二次再调用时中断状态已经被清除,将返回一个 false 。
*/
Thread.currentThread().interrupt();///----false---> true
System.out.println("222222");
System.out.println(Thread.currentThread().getName() + "---" + Thread.interrupted());
System.out.println(Thread.currentThread().getName() + "---" + Thread.interrupted());
}
}
返回结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=65487:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/tools.jar:/Users/shishizan/2022-java/大厂JUC/代码/juc2021/target/classes:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter-web/2.4.3/spring-boot-starter-web-2.4.3.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter/2.4.3/spring-boot-starter-2.4.3.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter-logging/2.4.3/spring-boot-starter-logging-2.4.3.jar:/Users/shishizan/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/Users/shishizan/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/Users/shishizan/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.13.3/log4j-to-slf4j-2.13.3.jar:/Users/shishizan/.m2/repository/org/apache/logging/log4j/log4j-api/2.13.3/log4j-api-2.13.3.jar:/Users/shishizan/.m2/repository/org/slf4j/jul-to-slf4j/1.7.30/jul-to-slf4j-1.7.30.jar:/Users/shishizan/.m2/repository/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5.jar:/Users/shishizan/.m2/repository/org/yaml/snakeyaml/1.27/snakeyaml-1.27.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter-json/2.4.3/spring-boot-starter-json-2.4.3.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.11.4/jackson-databind-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.11.4/jackson-annotations-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.11.4/jackson-core-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.11.4/jackson-datatype-jdk8-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.11.4/jackson-datatype-jsr310-2.11.4.jar:/Users/shishizan/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.11.4/jackson-module-parameter-names-2.11.4.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/2.4.3/spring-boot-starter-tomcat-2.4.3.jar:/Users/shishizan/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/9.0.43/tomcat-embed-core-9.0.43.jar:/Users/shishizan/.m2/repository/org/glassfish/jakarta.el/3.0.3/jakarta.el-3.0.3.jar:/Users/shishizan/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.43/tomcat-embed-websocket-9.0.43.jar:/Users/shishizan/.m2/repository/org/springframework/spring-web/5.3.4/spring-web-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-beans/5.3.4/spring-beans-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-webmvc/5.3.4/spring-webmvc-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-aop/5.3.4/spring-aop-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-context/5.3.4/spring-context-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-expression/5.3.4/spring-expression-5.3.4.jar:/Users/shishizan/.m2/repository/org/openjdk/jol/jol-core/0.9/jol-core-0.9.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-devtools/2.4.3/spring-boot-devtools-2.4.3.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot/2.4.3/spring-boot-2.4.3.jar:/Users/shishizan/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.4.3/spring-boot-autoconfigure-2.4.3.jar:/Users/shishizan/.m2/repository/org/projectlombok/lombok/1.18.18/lombok-1.18.18.jar:/Users/shishizan/.m2/repository/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar:/Users/shishizan/.m2/repository/org/springframework/spring-core/5.3.4/spring-core-5.3.4.jar:/Users/shishizan/.m2/repository/org/springframework/spring-jcl/5.3.4/spring-jcl-5.3.4.jar com.atguigu.juc.interrupt.InterruptDemoCopy
main---false
main---false
111111
222222
main---true
main---false
Process finished with exit code 0
静态方法与实例方法的对比


![]()

方法的注释也清晰的表达了“中断状态将会根据传入的ClearInterrupted参数值确定是否重置”。
所以,
静态方法interrupted将 会清除中断状态(传入的参数ClearInterrupted为true),
实例方法isInterrupted则不会(传入的参数ClearInterrupted为false)。
1.5、总结
线程中断相关的方法:
interrupt()方法是一个实例方法
它通知目标线程中断,也就是设置目标线程的中断标志位为true,中断标志位表示当前线程已经被中断了。
isInterrupted()方法也是一个实例方法
它判断当前线程是否被中断(通过检查中断标志位)并获取中断标志
Thread类的静态方法interrupted()
返回当前线程的中断状态(boolean类型)且将当前线程的中断状态设为false,此方法调用之后会清除当前线程的中断标志位的状态(将中断标志置为false了),返回当前值并清零置false
2、LockSupport是什么

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。
下面这句话,后面详细说
LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程
3、线程等待唤醒机制
3.1、3种让线程等待和唤醒的方法
方式1:使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒线程
方式2:使用JUC包中Condition的await()方法让线程等待,使用signal()方法唤醒线程
方式3:LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程
3.2、Object类中的wait和notify方法实现线程等待和唤醒
正常代码:
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/**
* @auther zzyy
* @create 2020-07-10 14:05
*/
public class LockSupportDemoCopy {
public static void main(String[] args)//main 方法,主线程一切程序入口
{
Object objectLock = new Object();
// 同一把锁,类似资源类
new Thread(() -> {
synchronized (objectLock) {
System.out.println(Thread.currentThread().getName()+"\t"+"---come in");
try {
objectLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " \t " + " 被唤醒了 ");
}, "t1").start();
// 暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(3L);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
synchronized (objectLock) {
objectLock.notify();
System.out.println(Thread.currentThread().getName()+"\t"+"---发出通知");
}
}, "t2").start();
}
}
异常代码1:wait方法和notify方法,两个都去掉同步代码块
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/**
* @auther zzyy
* @create 2020-07-10 14:05
*/
public class LockSupportDemoCopy {
public static void main(String[] args)//main 方法,主线程一切程序入口
{
Object objectLock = new Object();
// 同一把锁,类似资源类
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t" + "---come in");
try {
objectLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " \t " + " 被唤醒了 ");
}, "t1").start();
// 暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(3L);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
objectLock.notify();
System.out.println(Thread.currentThread().getName() + "\t" + "---发出通知");
}, "t2").start();
}
}
异常代码2:将notify放在wait方法前面,程序无法执行,无法唤醒
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/**
* @auther zzyy
* @create 2020-07-10 14:05
*/
public class LockSupportDemoCopy {
public static void main(String[] args)//main 方法,主线程一切程序入口
{
Object objectLock = new Object();
// 同一把锁,类似资源类
new Thread(() -> {
synchronized (objectLock) {
System.out.println(Thread.currentThread().getName() + "\t" + "---come in");
objectLock.notify();
System.out.println(Thread.currentThread().getName() + "\t" + "---发出通知");
}
}, "t1").start();
// 暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(3L);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
synchronized (objectLock) {
try {
objectLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " \t " + " 被唤醒了 ");
}, "t2").start();
}
} 
小总结:
- wait和notify方法必须要在同步块或者方法里面,且成对出现使用
- 先wait后notify才OK
3.3、Condition接口中的await后signal方法实现线程的等待和唤醒
正常代码:
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/**
* @auther zzyy
* @create 2020-07-10 14:05
*/
public class LockSupportDemoCopy {
static Lock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
public static void main(String[] args)//main 方法,主线程一切程序入口
{
new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "\t" + "---come in");
condition.await();
System.out.println(Thread.currentThread().getName() + "\t" + "---被唤醒");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "t1").start();
// 暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(3L);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
lock.lock();
try {
condition.signal();
System.out.println(Thread.currentThread().getName() + "\t" + "---发出通知");
} finally {
lock.unlock();
}
}, "t2").start();
}
} 
异常代码1:去掉lock/unlock
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/**
* @auther zzyy
* @create 2020-07-10 14:05
*/
public class LockSupportDemoCopy {
static Lock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
public static void main(String[] args)//main 方法,主线程一切程序入口
{
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + "\t" + "---come in");
condition.await();
System.out.println(Thread.currentThread().getName() + "\t" + "---被唤醒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t1").start();
// 暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(3L);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
try {
condition.signal();
System.out.println(Thread.currentThread().getName() + "\t" + "---发出通知");
} catch (Exception e) {
e.printStackTrace();
}
}, "t2").start();
}
}
condition.await();和 condition.signal();都触发了 IllegalMonitorStateException异常。
结论:
lock、unlock对里面才能正确调用调用condition中线程等待和唤醒的方法
异常代码2:先signal后await
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/**
* @auther zzyy
* @create 2020-07-10 14:05
*/
public class LockSupportDemoCopy {
static Lock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
public static void main(String[] args)//main 方法,主线程一切程序入口
{
new Thread(() -> {
lock.lock();
try {
condition.signal();
System.out.println(Thread.currentThread().getName() + "\t" + "---发出通知");
} finally {
lock.unlock();
}
}, "t1").start();
// 暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(3L);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "\t" + "---come in");
condition.await();
System.out.println(Thread.currentThread().getName() + "\t" + "---被唤醒");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "t2").start();
}
}代码运行无法结束:线程无法被唤醒

小总结:
- Condtion中的线程等待和唤醒方法之前,需要先获取锁
- 一定要先await后signal,不要反了
3.4、Object和Condition使用的限制条件
线程先要获得并持有锁,必须在锁块(synchronized或lock)中
必须要先等待后唤醒,线程才能够被唤醒
3.5、LockSupport类中的park等待和unpark唤醒
3.5.1、是什么
通过park()和unpark(thread)方法来实现阻塞和唤醒线程的操作
官方解释:

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。
LockSupport类使用了一种名为Permit(许可)的概念来做到 阻塞和唤醒线程 的功能, 每个线程都有一个许可(permit),
permit只有两个值1和零,默认是零。
可以把许可看成是一种(0,1)信号量(Semaphore),但与 Semaphore 不同的是,许可的累加上限是1。
3.5.2、主要方法
3.5.2.1、API

3.5.2.2、阻塞
park() /park(Object blocker)
调用 LockSupport. park ()时

permit默认是零,所以一开始调用park()方法,当前线程就会阻塞,直到别的线程将当前线程的permit设置为1时,park方法会被唤醒,
然后会将permit再次设置为零并返回。
阻塞当前线程/阻塞传入的具体线程
3.5.2.3、唤醒
unpark(Thread thread)
LockSupport. unpark (thread);

调用unpark(thread)方法后,就会将thread线程的许可permit设置成1(注意多次调用unpark方法,不会累加,permit值还是1)会自动唤醒thread线程,即之前阻塞中的LockSupport.park()方法会立即返回。
唤醒处于阻塞状态的指定线程
3.5.3、代码
3.5.3.1、正常+无锁块要求
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/**
* @auther zzyy
* @create 2020-07-10 14:05
*/
public class LockSupportDemoCopy {
static Lock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
public static void main(String[] args)//main 方法,主线程一切程序入口
{
Thread t1 = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t" + "---come in");
LockSupport.park();
System.out.println(Thread.currentThread().getName() + "\t" + "---被唤醒");
}, "t1");
t1.start();
try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
new Thread(() -> {
LockSupport.unpark(t1);
System.out.println(Thread.currentThread().getName()+"\t"+"---发出通知");
},"t2").start();
}
}
3.5.3.2、之前错误的先唤醒后等待,LockSupport照样支持
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/**
* @auther zzyy
* @create 2020-07-10 14:05
*/
public class LockSupportDemoCopy {
static Lock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
public static void main(String[] args)//main 方法,主线程一切程序入口
{
Thread t1 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t" + System.currentTimeMillis() + "\t" + "---come in");
LockSupport.park();
System.out.println(Thread.currentThread().getName() + "\t" + System.currentTimeMillis() + "\t" + "---被唤醒");
}, "t1");
t1.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
LockSupport.unpark(t1);
System.out.println(Thread.currentThread().getName() + "\t" + System.currentTimeMillis() + "\t" + "---发出通知");
}, "t2").start();
}
}
3.5.3.3、异常情况:没有考虑到 permit 上限值为 1
package com.atguigu.juc.interrupt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/**
* @auther zzyy
* @create 2020-07-10 14:05
*/
public class LockSupportDemoCopy {
static Lock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
public static void main(String[] args)//main 方法,主线程一切程序入口
{
Thread t1 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t" + "---come in");
LockSupport.park();
LockSupport.park();
System.out.println(Thread.currentThread().getName() + "\t" + "---被唤醒");
}, "t1");
t1.start();
new Thread(() -> {
LockSupport.unpark(t1);
LockSupport.unpark(t1);
System.out.println(Thread.currentThread().getName() + "\t" + "---发出通知");
}, "t2").start();
}
}程序运行结果:由于 permit 的上限值为 1,所以执行两次 LockSupport.park() 操作将导致 t1 线程阻塞

LockSupport和每个使用它的线程都有一个许可(permit)关联。permit相当于1,0的开关,默认是0,调用一次unpark就加1变成1,调用一次park会消费permit,也就是将1变成0,同时park立即返回。
如再次调用park会变成阻塞(因为permit为零了会阻塞在这里,一直到permit变为1),这时调用unpark会把permit置为1。
每个线程都有一个相关的permit,permit最多只有一个,重复调用unpark也不会积累凭证。
线程阻塞需要消耗凭证(permit),这个凭证最多只有1个。
1、当调用park方法时
如果有凭证,则会直接消耗掉这个凭证然后正常退出;
如果无凭证,就必须阻塞等待凭证可用;
2、而unpark则相反,它会增加一个凭证,但凭证最多只能有1个,累加无效。
边栏推荐
- 12. AQS of abstractqueuedsynchronizer
- 记一次 mysql 主从不同步问题排查
- 你管这破玩意儿叫 MQ?
- .net core 抛异常对性能影响的求证之路
- C # convert ofd to PDF
- Take you to know about direct insertion sorting (C language)
- 中国联通 22春招 群面
- 9、聊聊ThreadLocal
- Splunk manually synchronize search head
- UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xc5 in position 13: invalid continuation byte
猜你喜欢

ftp服务器:serv-u 的下载及使用

中国网络安全年会周鸿祎发言:360安全大脑构筑数据安全体系

【LeetCode】494. Objective and (2 wrong questions)

Flick grouping sets multidimensional aggregation and setting table state expiration time

Flink spark vs. Flink

The secret behind the Splunk bucket

C # set or verify the format of text field in PDF

Flink time semantics, watermark, generated watermark, and transmission of watermark

Flink data flow graph, parallelism, operator chain, jobgraph and executiongraph, task and task slot

Splunk健康检查orphaned searches
随机推荐
JVM optimization
How does data age in Splunk?
saltstack安装与使用
合并两个有序数组(C语言)
Splunk Bucket 背后的秘密
Flink physical partition (random partition, polling partition, rescaling partition, broadcast, global partition, custom partition)
纯数据业务的机器打电话进来时回落到了2G/3G
InputStream read file OutputStream create file
Merge two ordered arrays (C language)
微信授权获取手机号码
C # apply many different fonts in PDF documents
ftp服務器:serv-u 的下載及使用
Flink data flow graph, parallelism, operator chain, jobgraph and executiongraph, task and task slot
splunk 证书过期 使KV-store不能启动
一般运维架构图
9、聊聊ThreadLocal
Zero after factorial (C language)
Progress bar loading
9. Parler de threadlocal
线程五种状态(线程生命周期)