多线程
文章平均质量分 81
wyaoyao93
小白
展开
-
多线程设计模式:Active Objects设计模式(TODO)
文章目录1 接受异步消息的主动对象2 标准Active Objects模式设计2.1 准备调用接口1 接受异步消息的主动对象Active是“主动”的意思,Active Object是“主动对象”的意思,所谓主动对象就是指其拥有自己的独立线程,比如java.lang.Thread实例就是一个主动对象,不过Active Object Pattern不仅仅是拥有独立的线程,它还可以接受异步消息,并且能够返回处理的结果。System.gc方法就是一个“接受异步消息的主动对象”,调用gc方法的线程和gc自身原创 2021-04-13 17:18:46 · 190 阅读 · 0 评论 -
多线程设计模式:Worker-Thread设计模式(流水线)
Worker-Thread模式有时也称为流水线设计模式线程池在某种意义上也算是Worker-Thread模式的一种实现,线程池初始化时所创建的线程类似于在流水线等待工作的工人,提交给线程池的Runnable接口类似于需要加工的产品,而Runnable的run方法则相当于组装该产品的说明书。文章目录1 Worker-Thread模式实现1.1 产品及组装说明书1.2 流水线传送带1.3 流水线工人1.3 测试2 Worker-Thread和Producer-Consumer1 Worker-Th.原创 2021-04-13 10:54:16 · 1058 阅读 · 0 评论 -
强引用和弱引用
无论是File还是Socket等重量级的资源(严重依赖操作系统资源),在进行释放时并不能百分之百的保证成功(可能是操作系统的原因),对socket的关闭有可能会失败,然后socket的实例会被垃圾回收器回收,但是socket实例对应的底层系统资源或许并未释放。那么我们有什么办法可以再次尝试对socket进行资源释放操作呢?1 Strong Reference及LRUCache1.1 LRUCacheCache是一种用于提高系统性能,提高数据检索效率的机制,而LRU(Least recently.原创 2021-04-12 13:05:44 · 138 阅读 · 0 评论 -
多线程设计模式:Two Phase Termination设计模式
文章目录1 什么是Two Phase Termination模式1 什么是Two Phase Termination模式当一个线程正常结束,或者因被打断而结束,或者因出现异常而结束时,我们需要考虑如何同时释放线程中资源,比如文件句柄、socket套接字句柄、数据库连接等比较稀缺的资源当希望结束这个线程时,发出线程结束请求,接下来线程不会立即结束,而是会执行相应的资源释放动作直到真正的结束,在终止处理状态时,线程虽然还在运行,但是进行的是终止处理工作,因此终止处理又称为线程结束的第二个阶段,而受理终原创 2021-04-10 21:09:55 · 141 阅读 · 0 评论 -
多线程设计模式:Thread-Per-Message设计模式
文章目录1 什么是Thread-Per-Message模式2 每个任务一个线程3 多用户的网络聊天1 什么是Thread-Per-Message模式Thread-Per-Message的意思是为每一个消息的处理开辟一个线程使得消息能够以并发的方式进行处理,从而提高系统整体的吞吐能力。这就好比电话接线员一样,收到的每一个电话投诉或者业务处理请求,都会提交对应的工单,然后交由对应的工作人员来处理2 每个任务一个线程定义一个请求:public class Request { /**原创 2021-04-10 20:35:27 · 143 阅读 · 0 评论 -
多线程设计模式:Latch(门阀)设计模式
1什么是Latch若干线程并发执行某个特定的任务,然后等到所有的子任务都执行结束之后再统一汇总,比如用户想要查询自己三年以来银行账号的流水,为了保证运行数据库的数据量在一个恒定的范围之内,通常数据只会保存一年的记录,其他的历史记录或被备份到磁盘,或者被存储于hive数据仓库,或者被转存至备份数据库之中,总之想要三年的流水记录,需要若干个渠道的查询才可以汇齐。如果一个线程负责执行这样的任务,则需要经历若干次的查询最后汇总返回给用户,很明显这样的操作性能低下,用户体验差,如果我们将每一个渠道的查询交给一个线程原创 2021-04-10 20:06:13 · 311 阅读 · 0 评论 -
多线程设计模式:Balking设计模式
1 什么是Balking设计模式多个线程监控某个共享变量,A线程监控到共享变量发生变化后即将触发某个动作,但是此时发现有另外一个线程B已经针对该变量的变化开始了行动,因此A便放弃了准备开始的工作,我们把这样的线程间交互称为Balking(犹豫)设计模式。其实这样的场景在生活中很常见,比如你去饭店吃饭,吃到途中想要再点一个小菜,于是你举起手示意服务员,其中一个服务员看到了你举手正准备走过来的时候,发现距离你比较近的服务员已经准备要受理你的请求于是中途放弃了。我们在用word编写文档的时候,每次的文字编辑原创 2021-04-10 18:48:51 · 131 阅读 · 0 评论 -
ThreadLocal详解
文章目录1 线程上下文设计2 ThreadLocal2.1 ThreadLocal的使用场景及注意事项2.2 ThreadLocal的方法详解及源码分析2.2.1 简单认识2.2.2 常用方法initialValueset方法get方法2.2.3 ThreadLocalMapThreadLocal的内存泄漏问题分析1 线程上下文设计单个线程执行的任务步骤会非常多,后一个步骤的输入有可能是前一个步骤的输出,比如在单个线程多步骤(阶段)执行时,为了使得功能单一,有时候我们会采用GoF职责链设计模式:原创 2021-04-10 17:53:30 · 182 阅读 · 0 评论 -
多线程设计模式:Future设计模式
文章目录1 引入2 简单实现2.1 接口定义2.1.1 Future接口设计2.1.2 Runnbale接口替代接口:Task接口2.1.3 FutureService接口2.2 接口实现2.2.1 Future接口实现: FutureTask2.2.2 FutureService实现3 测试3.1 无返回值测试3.2 测试有返回值4 增强FutureService使其支持回调:1 引入假设有个任务需要执行比较长的的时间,通常需要等待任务执行结束或者出错才能返回结果,在此期间调用者只能陷入阻塞苦苦等待,原创 2021-04-10 13:29:17 · 313 阅读 · 0 评论 -
多线程设计模式:不可变对象设计模式
所谓共享的资源,是指在多个线程同时对其进行访问的情况下,各线程都会使其发生变化,而线程安全性的主要目的就在于在受控的并发访问中防止数据发生变化。除了使用synchronized关键字同步对资源的写操作之外,还可以在线程之间不共享资源状态,甚至将资源的状态设置为不可变。在本章中,我们将讨论如何设计不可变对象,这样就可以不用依赖于synchronized关键字的约束。文章目录1 不可变对象认识2 累加器2.1 非安全累加器1 不可变对象认识Java核心类库中提供了大量的不可变对象范例,其中java..原创 2021-04-10 11:41:39 · 148 阅读 · 0 评论 -
多线程设计模式: 读写锁分离设计模式
文章目录1 场景引入2 读写分离模式设计1 场景引入在多线程的情况下访问共享资源,需要对资源进行同步操作以防止数据不一致的情况发生,通常我们可以使用synchronized关键字或者显式锁。对资源的访问一般包括两种类型的动作——读和写(更新、删除、增加等资源会发生变化的动作),如果多个线程在某个时刻都在进行资源的读操作,虽然有资源的竞争,但是这种竞争不足以引起数据不一致的情况发生,那么这个时候直接采用排他的方式加锁,就显得有些简单粗暴了。**其实多线程在同一时间都进行读操作时不会引起冲突之外,其余的原创 2021-04-05 21:51:13 · 383 阅读 · 0 评论 -
多线程设计模式:Single Thread Execution设计模式
Single Thread Execution模式是指在同一时刻只能有一个线程去访问共享资源,就像独木桥一样每次只允许一人通行,简单来说,Single Thread Execution就是采用排他式的操作保证在同一时刻只能有一个线程访问共享资源。文章目录1 场景举例:安检1.1 非线程安全实现1.2 数据不一致原因分析1.3 解决数据不一致问题(改为线程安全)1 场景举例:安检在进入登机口之前必须经过安全检查,安检口类似于独木桥,每次只能通过一个人,工作人员除了检查你的登机牌以外,还要联网检查身.原创 2021-04-05 21:43:17 · 342 阅读 · 1 评论 -
多线程设计模式:监控任务的声明周期(观察者模式)
文章目录1 场景描述2 观察者模式3 实现3.1 接口定义3.1.1 Observable接口定义(被观察者)3.1.2 TaskLifecycle接口定义(观察者)3.1.3 Task函数接口定义3.2 接口实现3.2.1 ObservableThread实现4 测试5 总结1 场景描述虽然Thread为我们提供了可获取状态,以及判断是否alive的方法,但是这些方法均是针对线程本身的,而我们提交的任务Runnable在运行过程中所处的状态如何是无法直接获得的,比如它什么时候开始,什么时候结束,最不原创 2021-04-05 19:45:21 · 276 阅读 · 1 评论 -
单例模式实现
文章目录1 饿汉式懒汉式解决懒汉式的线程不安全方案一方案二ClassHolder枚举方式1 饿汉式/** * @author :wyaoyao * @date : 2020-04-06 14:32 * 单例模式:饿汉式 * 线程安全 * 但是在不使用的时候占用内存,因为通过static是类主动加载,不能能够懒加载 */public class SingletonSimple1 { private static final SingletonSimple1 instance = n原创 2020-09-10 19:55:09 · 83 阅读 · 0 评论 -
深入volatile关键字(二)volatile特性,使用场景,volatile和synchronized区别
前面两篇都是对volatile进行铺垫:volatile关键字引入(CPU缓存模型,数据一致性,java内存模型)深入volatile关键字(一)并发编程的三个重要特性和指令重排以及Happens-before原则:文章目录1 volatile关键字的语义1.1 理解volatile保证可见性1.2 理解volatile保证顺序性1.3 理解volatile不保证原子性2 内存屏障(了解)3 volatile的使用场景3.1 开关控制3.2 状态标记3.3 Singleton设计模式(单例模.原创 2021-04-05 11:07:37 · 294 阅读 · 1 评论 -
深入volatile关键字(一)并发编程的三个重要特性和指令重排以及Happens-before原则
文章目录1 并发编程的三个重要特性1.1 原子性1.2 可见性1.3 有序性1.3.1 指令重排2 JMM(Java的内存模型)如何保证三大特性2.1 JMM与原子性1 并发编程的三个重要特性1.1 原子性原子性是指在一次的操作或者多次操作中,要么所有的操作全部都得到了执行并且不会受到任何因素的干扰而中断,要么所有的操作都不执行。说起原子性一般都会用银行转账来进行举例说明,比如从Alex的账号往Tina的账号转入1000元,这个动作将包含两个最基本的操作:从Alex的账号上扣除1000元;给T原创 2021-04-04 23:25:09 · 359 阅读 · 2 评论 -
volatile关键字引入(CPU缓存模型,数据一致性,java内存模型)
自Java 1.5版本起,volatile关键字所扮演的角色越来越重要,该关键字也成为并发包的基础,所有的原子数据类型都以此作为修饰,相比synchronized关键字,volatile被称为“轻量级锁”,能实现部分synchronized关键字的语义。volatile是一个非常重要的关键字,虽然看起来很简单,但是想要彻底弄清楚volatile的来龙去脉还是需要具备Java内存模型、CPU缓存模型等知识的文章目录1 初识volatile关键字1.1 入门程序2 CPU Cache模型2.1 C.原创 2021-04-04 23:05:44 · 201 阅读 · 1 评论 -
线程上下文类加载器
文章目录1 为什么需要线程上下文类加载器1.1 为什么要有线程上下文类加载器呢1.2 数据库驱动的初始化源码分析1 为什么需要线程上下文类加载器线程上下文方法是从JDK1.2开始引入的,getContextClassLoader和setContextClassLoader(ClassLoader cl)分别用于获取和设置当前线程的上下文类加载器,如果当前线程没有设置上下文类加载器,那么它将和父线程保持同样的类加载器。/**获取当前线程的上下文类加载器**/public ClassLoader g原创 2021-04-04 21:44:12 · 233 阅读 · 0 评论 -
类加载器命名空间、运行时包、类的卸载
文章目录1 类加载器命名空间2 运行时包3 初始类加载器4 类的卸载5 测试: 自定义一个java.lang.String1 类加载器命名空间每一个类加载器实例都有各自的命名空间,命名空间是由该加载器及其所有父加载器所构成的,因此在每个类加载器中同一个class都是独一无二的public class NameSpaceTest { public static void main(String[] args) throws ClassNotFoundException { Cl原创 2021-04-04 18:05:03 · 376 阅读 · 0 评论 -
双亲委托机制
可先阅读:JVM类加载器文章目录1 双亲委托机制介绍2 破坏双亲委托机制1 双亲委托机制介绍类加载器最重要的机制——双亲委托机制,有时候也称为父委托机制。当一个类加载器被调用了loadClass之后,它并不会直接将其加载,而是先交给当前类加载器的父加载器尝试加载直到最顶层的父加载器,然后再依次向下进行加载loadClass方法源码:public Class<?> loadClass(String name) throws ClassNotFoundException { .原创 2021-04-04 17:03:33 · 277 阅读 · 1 评论 -
JVM类加载器
类的加载器就是负责类的加载职责,对于任意一个class,都需要由加载它的类加载器和这个类本身确立其在JVM中的唯一性,这也就是运行时包,任何一个对象的class在JVM中只存在唯一的一份,比如String.class、Object.class在堆内存以及方法区中肯定是唯一的,但是不能绝对地理解为我们自定义的类在JVM中同样也是这样文章目录1 JVM内置三大类加载器1.1 Bootstrap类加载器介绍(根类加载器)1.2 ExtClassLoader(扩展类加载器)介绍1.3 ApplicationC.原创 2021-04-04 14:49:08 · 132 阅读 · 2 评论 -
类的加载过程
文章目录1 类的加载过程简介2 类的主动使用和被动使用2.1 类的主动使用2.2 类的被动使用2.3 类的主动和被动使用两个易混淆的例子3 类的加载过程详解3.1 思考3.2 类的加载阶段3.3 类的连接阶段3.3.1 验证过程3.3.2 准备过程3.2.3 解析过程3.4 类的初始化阶段1 类的加载过程简介ClassLoader的主要职责就是负责加载各种class文件到JVM中,ClassLoader是一个抽象的class,给定一个class的二进制文件名,ClassLoader会尝试加载并且在JV原创 2021-04-03 22:20:50 · 235 阅读 · 0 评论 -
线程池原理和自定义实现
文章目录1 线程池原理2 简单实现一个线程池JDK1.5起,utils包提供了ExecutorService线程池的实现,主要目的是为了重复利用线程,提高系统效率。Thread是一个重量级的资源,创建、启动以及销毁都是比较耗费系统资源的,因此对线程的重复利用一种是非常好的程序设计习惯,加之系统中可创建的线程数量是有限的,线程数量和系统性能是一种抛物线的关系,也就是说当线程数量达到某个数值的时候,性能反倒会降低很多,因此对线程的管理,尤其是数量的控制更能直接决定程序的性能。1 线程池原理所谓线程池,通俗原创 2021-04-03 19:13:01 · 108 阅读 · 0 评论 -
Hook线程和捕获线程执行异常
文章目录1 获取线程运行时异常1.1 UncaughtExceptionHandler接口介绍和实现1.1.1 UncaughtExceptionHandler接口介绍1.1.2 UncaughtExceptionHandler接口示例1.1.3 UncaughtExceptionHandler源码分析2 注入钩子线程2.1 Hook线程介绍2.2 Hook线程实战2.3 Hook线程应用场景以及注意事项1 获取线程运行时异常在Thread类中:,关于处理运行时异常的API总共有四个:/**为某个特原创 2021-04-03 11:43:57 · 298 阅读 · 0 评论 -
ThreadGroup操作(API)
文章目录1基本操作1基本操作// 用于获取group中活跃的线程,这只是个估计值,并不能百分之百地保证数字一定正确,原因前面已经分析过,该方法会递归获取其他子group中的活跃线程。activeCount();// 用于获取group中活跃的子group,这也是一个近似估值,该方法也会递归获取所有的子group。activeGroupCount();// 用于获取group的优先级,默认情况下,Group的优先级为10,在该group中,所有线程的优先级都不能大于group的优先级。getMa原创 2021-04-02 22:31:08 · 89 阅读 · 0 评论 -
ThreadGroup介绍(线程组)
文章目录1 ThreadGroup介绍2 创建ThreadGroup3 复制Thread数组和ThreadGroup数组3.1 复制Thread数组3.2 复制ThreadGroup数组1 ThreadGroup介绍线程组代表一组线程。 此外,线程组还可以包括其他线程组。 线程组形成一个树,除了初始线程组之外,每个线程组都有一个父进程。允许线程访问有关其线程组的信息,但不能访问有关其线程组的父线程组或任何其他线程组的信息。在Thread的构造函数中,可以显式地指定线程的Group,也就是Thre原创 2021-04-02 22:16:44 · 1847 阅读 · 0 评论 -
自定义显式锁BooleanLock
构建一个自定义的显式锁,类似于Java utils包下的Lock接口,并且分析synchronized关键字的缺陷1 synchronized关键字的缺陷synchronized关键字提供了一种排他式的数据同步机制,某个线程在获取monitor lock的时候可能会被阻塞,而这种阻塞有两个很明显的缺陷:无法控制阻塞时长。阻塞不可被中断,一个线程一旦抢到synchronized同步锁,只要他不释放这个锁其他线程就只能阻塞,调用者也无法打断这些在等待抢锁的线程验证:无法控制阻塞时长。publi原创 2021-04-02 21:09:07 · 170 阅读 · 0 评论 -
线程休息室wait set
在虚拟机规范中存在一个wait set(wait set又被称为线程休息室)的概念,至于该wait set是怎样的数据结构,JDK官方并没有给出明确的定义,不同厂家的JDK有着不同的实现方式,甚至相同的JDK厂家不同的版本也存在着差异,但是不管怎样,线程调用了某个对象的wait方法之后都会被加入与该对象monitor关联的wait set中,并且释放monitor的所有权。若干个线程调用了wait方法之后被加入与monitor关联的wait set中,待另外一个线程调用该monitor的notify方法之原创 2021-04-01 14:39:59 · 295 阅读 · 0 评论 -
多线程间通信
1 问题引入:看个代码:@Slf4jpublic class ProduceConsumerDemo3 { // 数据 private int data = 0; final private Object lock = new Object(); // 标志:是否已经生产数据了 private volatile Boolean hasProduce = false; // 生产数据 private void produce() {原创 2021-04-01 14:23:24 · 73 阅读 · 0 评论 -
wait和sleep区别
1 sleep和wait区别从表面上看,wait和sleep方法都可以使当前线程进入阻塞状态,但是两者之间存在着本质的区别:wait和sleep方法都可以使线程进入阻塞状态。wait和sleep方法均是可中断方法,被中断后都会收到中断异常。wait是Object的方法,而sleep是Thread特有的方法。wait方法的执行必须在同步方法中进行,而sleep则不需要。线程在同步方法中执行sleep方法时,并不会释放monitor的锁,而wait方法则会释放monitor的锁,并且将线程添加到该原创 2021-04-01 11:04:15 · 861 阅读 · 0 评论 -
wait和notify方法详解
1 基本介绍1.1 wait方法wait和notify方法并不是Thread特有的方法,而是Object中的方法,也就是说在JDK中的每一个类都拥有这两个方法,那么这两个方法到底有什么神奇之处可以使线程阻塞又可以唤醒线程呢?我们先来说说wait方法,下面是wait方法的三个重载方法。public final void wait() throws InterruptedException// 指定等待超时时间public final void wait(long timeout) throws I原创 2021-04-01 10:56:39 · 798 阅读 · 0 评论 -
初识wait和notify(单线程通讯)
服务端有若干个线程会从队列中获取相应的Event进行异步处理,那么这些线程又是如何从队列中获取数据的呢?换句话说就是如何知道队列里此时是否有数据呢?比较笨的办法是不断地轮询:如果有数据则读取数据并处理,如果没有则等待若干时间再次轮询。还有一种比较好的方式就是通知机制:如果队列中有Event,则通知工作的线程开始工作;没有Event,则工作线程休息并等待通知。定义一个事件队列,储存客户端提交的的事件public class EventQueue { /** * 队列的最大容量原创 2021-04-01 09:44:40 · 149 阅读 · 0 评论 -
同步阻塞与异步非阻塞(简单了解)
1 同步阻塞消息处理假如有这样一个系统功能,客户端提交Event至服务器,服务器接收到客户请求之后开辟线程处理客户请求,经过比较复杂的业务计算后将结果返回给客户端图5-1所示的设计存在几个显著的缺陷,具体如下:同步Event提交,客户端等待时间过长(提交Event时长+接受Event创建thread时长+业务处理时长+返回结果时长)会陷入阻塞,导致二次提交Event耗时过长。由于客户端提交的Event数量不多,导致系统同时受理业务数量有限,也就是系统整体的吞吐量不高。这种一个线程处理一个Eve原创 2021-03-31 16:29:02 · 187 阅读 · 0 评论 -
程序死锁的原因以及如何诊断
1 程序死锁1.1 交叉锁可导致程序出现死锁线程A持有R1的锁等待获取R2的锁,线程B持有R2的锁等待获取R1的锁(典型的哲学家吃面),这种情况最容易导致程序发生死锁的问题1.2 内存不足当并发请求系统可用内存时,如果此时系统内存不足,则可能会出现死锁的情况。举个例子,两个线程T1和T2,执行某个任务,其中T1已经获取了10MB内存,T2获取了20MB内存,如果每个线程的执行单元都需要30MB的内存,但是剩余可用的内存刚好为20MB,那么两个线程有可能都在等待彼此能够释放内存资源。1.3 一问一原创 2021-03-31 16:01:13 · 1367 阅读 · 0 评论 -
深入synchronized关键字
文章目录1 线程堆栈分析2 JVM指令分析2.1 Monitorenter2.2 Monitorexit3 使用synchronized需要注意的问题4 This Monitor和Class Monitor的详细介绍4.1 This Monitor4.1.1 验证同步方法的monitor是this的monitor4.1.2 验证一下同步静态方法的monitor是class monitor1 线程堆栈分析synchronized关键字提供了一种互斥机制,也就是说在同一时刻,只能有一个线程访问同步资源,很原创 2021-03-31 15:18:57 · 140 阅读 · 0 评论 -
多线程之数据同步(初识synchronized关键字)
1 数据不一致问题的引入之前的一个窗口叫号程序:链接地址public class TicketRunnable implements Runnable{ /** * 定义50张门票 */ private final int TICKET_TOTAL = 500; private int index = 1; @Override public void run() { while (index <= TICKET_TO原创 2021-03-30 17:06:20 · 182 阅读 · 0 评论 -
线程的生命周期详解
每一个线程都有自己的局部变量表、程序计数器,以及生命周期等,本节就来分析一下线程的生命周期1 线程的NEW状态当我们用关键字new创建一个Thread对象时,此时它并不处于执行状态,因为没有调用start方法启动该线程,那么线程的状态为NEW状态,准确地说,它只是Thread对象的状态,因为在没有start之前,该线程根本不存在,与你用关键字new创建一个普通的Java对象没什么区别。NEW状态通过start方法进入RUNNABLE状态。2 线程的RUNNABLE状态(可执行状态)**线程对原创 2021-03-26 16:32:16 · 862 阅读 · 0 评论 -
Thread类API详解(四)-如何关闭一个线程
JDK有一个Deprecated方法stop,但是该方法存在一个问题,JDK官方早已经不推荐使用,其在后面的版本中有可能会被移除,根据官网的描述,该方法在关闭线程时可能不会释放掉monitor的锁,所以强烈建议不要使用该方法结束线程。1 正常关闭线程结束生命周期正常结束。线程运行结束,完成了自己的使命之后,就会正常退出,如果线程中的任务耗时比较短,或者时间可控,那么放任它正常结束就好了。捕获中断信号关闭线程,比如下面这段代码:上面的代码是通过检查线程interrupt的标识来决定是否退出的原创 2021-03-30 13:50:01 · 271 阅读 · 0 评论 -
Thread的API详细介绍(三)线程的join
1 join方法介绍当前线程等待子线程死亡,才会执行。与sleep一样它也是一个可中断的方法,也就是说,如果有其他线程执行了对当前线程的interrupt操作,它也会捕获到中断信号,并且擦除线程的interrupt标识,Thread的API为我们提供了三个不同的join方法,具体如下:public final void join() throws InterruptedExceptionpublic final synchronized void join(long millis,int nanos)原创 2021-03-30 10:49:07 · 123 阅读 · 0 评论 -
Thread的API详细介绍(二)线程的打断
文章目录1 线程打断(interrupt)1.1 interrupt()方法1.2 isInterrupted方法1.3 interrupted()方法1.4 isInterrupted和interrupted的其他说明1 线程打断(interrupt)// 打断线程public void interrupt();// 是否打断public static boolean interrupted();// 是否打断public boolean isInterrupted();1.1 inte原创 2021-03-28 22:30:35 · 325 阅读 · 0 评论