java mousepress_Java线程原语弃用

为什么是线程停止不赞成?

因为它本质上是不安全的。停止线程会使其解锁其锁定的所有监视器。(当ThreadDeath异常在堆栈上传播时,监视器将被解锁。)如果以前受这些监视器保护的任何对象处于不一致状态,其他线程现在可能会以不一致的状态查看这些对象。据说这些物品被损坏了。当线程对损坏的对象进行操作时,可能会导致任意行为。这种行为可能是微妙的,很难被发现,也可能是被宣布的。与其他未经检查的异常不同,ThreadDeath无声地杀死线程;因此,用户没有警告他的程序可能已损坏。腐败在实际损害发生后的任何时候都会显现出来,甚至在未来的几个小时或几天内也是如此。

为什么是线程停止我不能捕获ThreadDeath异常并修复损坏的对象吗?

从理论上讲,可能是这样,但这会使编写正确的多线程代码的任务变得非常复杂。这项任务几乎无法完成,原因有两个:

1.线程几乎可以在任何地方抛出ThreadDeath异常。所有同步的方法和块都必须非常详细地研究,记住这一点。

2.当从第一个线程(在catch或finally子句中)清除时,线程可以抛出第二个ThreadDeath异常。清理工作必须重复进行,直到成功为止。确保这一点的代码将非常复杂。

总之,这是不实际的。

那如何线程停止(可丢弃的)?

除上述所有问题外,此方法还可用于生成目标线程未准备好处理的异常(包括如果没有此方法,则线程不可能抛出的检查异常)。例如,以下方法在行为上与Java的抛出操作相同,但避免了编译器试图确保调用方法声明了它可能抛出的所有检查异常:

static void sneakyThrow(Throwable t) {

Thread.currentThread().stop(t);

}

我应该用什么来代替线程停止?

大多数停止的用法应该被简单地修改一些变量以指示目标线程应该停止运行的代码所取代。目标线程应该定期检查该变量,如果变量指示要停止运行,则应该以有序的方式从它的run方法返回。为了确保停止请求的快速通信,变量必须是易失性的(或者对变量的访问必须是同步的)。例如,假设您的applet包含以下启动、停止和运行方法:

private Thread blinker;

public void start() {

blinker = new Thread(this);

blinker.start();

}

public void stop() {

blinker.stop(); // UNSAFE!

}

public void run() {

while (true) {

try {

Thread.sleep(interval);

} catch (InterruptedException e){

}

repaint();

}

}

可以通过将applet的停止和运行方法替换为:

private volatile Thread blinker;

public void stop() {

blinker = null;

}

public void run() {

Thread thisThread = Thread.currentThread();

while (blinker == thisThread) {

try {

Thread.sleep(interval);

} catch (InterruptedException e){

}

repaint();

}

}

如何停止等待很长时间的线程(例如,等待输入)?

这就是线程.中断方法的作用所在。可以使用相同的“基于状态”的信令机制,但状态更改(在前面的示例中,闪烁值=NULL)之后可以调用Thread.中断,以中断等待:

public void stop() {

Thread moribund = waiter;

waiter = null;

moribund.interrupt();

}

要使此技术有效,任何捕获中断异常且不准备立即处理该异常的方法都必须重新声明异常。我们说的是重抛而不是重新抛出,因为重新抛出异常并不总是可能的。如果未声明捕获InterruptedException的方法抛出此(已检查)异常,则应使用以下咒语“重新中断自身”:

Thread.currentThread().interrupt();

这将确保线程一旦能够恢复InterruptedException。

如果线程没有响应线程。中断怎么办?

在某些情况下,您可以使用特定于应用程序的技巧。例如,如果线程正在等待已知的套接字,则可以关闭套接字以使线程立即返回。不幸的是,实际上没有任何技术在一般情况下起作用。应该注意的是,在所有等待线程不响应Thread.中断的情况下,它也不会响应Thread.Stop。这种情况包括蓄意拒绝服务攻击,以及I/O操作,这些操作的线程.停止和线程.中断不能正常工作。

为什么线程暂停和线程恢复不再受欢迎?

线程。挂起天生容易死锁。如果目标线程在监视器上持有一个锁,在关键系统资源挂起时保护该资源,则在目标线程恢复之前,任何线程都不能访问该资源。如果要恢复目标线程的线程在调用resume之前尝试锁定此监视器,则会导致死锁。这种死锁通常表现为“冻结”进程。

我应该用什么来代替线程暂停和线程恢复?

与Thread.top一样,谨慎的方法是让“目标线程”轮询一个变量,该变量指示线程的所需状态(活动或挂起)。当所需的状态被挂起时,线程将使用Object.Wait等待。

当线程被恢复时,目标线程将被使用Object.Notification通知。例如,假设您的applet包含以下mousePress事件处理程序,该处理程序将切换名为闪烁器的线程的状态:

private boolean threadSuspended;

Public void mousePressed(MouseEvent e) {

e.consume();

if (threadSuspended)

blinker.resume();

else

blinker.suspend(); // DEADLOCK-PRONE!

threadSuspended = !threadSuspended;

}

可以通过将上面的事件处理程序替换为:

public synchronized void mousePressed(MouseEvent e) {

e.consume();

threadSuspended = !threadSuspended;

if (!threadSuspended)

notify();

}

并将以下代码添加到“Run循环”中:

synchronized(this) {

while (threadSuspended)

wait();

}

等待方法抛出InterruptedException,因此它必须在一次尝试中.捕获条款。把它和睡眠放在同一个条款里是可以的。检查应该跟随(而不是在睡眠之前),因此当线程“恢复”时,立即重新绘制窗口。得到的Run方法如下:

public void run() {

while (true) {

try {

Thread.sleep(interval);

synchronized(this) {

while (threadSuspended)

wait();

}

} catch (InterruptedException e){

}

repaint();

}

}

注意,mousePress方法中的Notification和Run方法中的Wait都在同步块中。这是语言所要求的,并确保等待和通知被正确序列化。实际上,这消除了可能导致“挂起”线程丢失通知并无限期挂起的争用条件。

虽然Java中的同步成本随着平台的成熟而降低,但它永远不会是免费的。可以使用一个简单的技巧来删除我们添加到“Run循环”每次迭代中的同步。添加的同步块被稍微复杂一些的代码替换,只有在线程实际挂起时才进入同步块:

if (threadSuspended) {

synchronized(this) {

while (threadSuspended)

wait();

}

}

在没有显式同步的情况下,必须使线程悬挂不稳定,以确保暂停请求的及时通信。结果的Run方法是:

private volatile boolean threadSuspended;

public void run() {

while (true) {

try {

Thread.sleep(interval);

if (threadSuspended) {

synchronized(this) {

while (threadSuspended)

wait();

}

}

} catch (InterruptedException e){

}

repaint();

}

}

能否将这两种技术结合起来,生成一个可以安全“停止”或“挂起”的线程?

是的,很简单。其中一个微妙之处是,当另一个线程试图停止目标线程时,该线程可能已经挂起。如果stop方法只是将状态变量(blinker)设置为null,那么目标线程将保持挂起状态(在监视器上等待),而不是正常退出。如果重新启动小程序,多个线程可能会同时等待监视器,从而导致不稳定的行为。

要纠正这种情况,stop方法必须确保目标线程在挂起时立即恢复。一旦目标线程恢复,它必须立即意识到它已经停止,并优雅地退出。下面是生成的run和stop方法的外观:

public void run() {

Thread thisThread = Thread.currentThread();

while (blinker == thisThread) {

try {

Thread.sleep(interval);

synchronized(this) {

while (threadSuspended && blinker==thisThread)

wait();

}

} catch (InterruptedException e){

}

repaint();

}

}

public synchronized void stop() {

blinker = null;

notify();

}

如上文所述,如果停止方法调用Thread.中断,它也不必调用Notification,但它仍然必须是同步的。这可以确保目标线程不会因为争用条件而错过中断。

那如何线程销毁?

线程破坏性从来没有实现过,并且已经被废弃了。如果实现了它,就会以线程销毁的方式出现死锁。(实际上,它大致相当于Thread.休会,而不可能出现后续的Thread.Response)。

为什么是运行时.runFinalizersOnExit不赞成?

因为它本质上是不安全的。它可能导致在活动对象上调用终结器,而其他线程则同时操作这些对象,从而导致异常行为或死锁。虽然这个问题是可以避免的,如果其对象正在最后确定的类被编码为“防御”这个调用,大多数程序员不抵抗它。它们假设对象在调用终结器时已经死亡。此外,调用并不是“线程安全”,因为它设置了VM全局标志。这迫使每个类使用终结器来防御活动对象的终结!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346743.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

带有Jersey的JAX-RS教程,用于RESTful Web服务

在当今世界,数据扮演着非常重要的角色。 如此众多的应用程序将各种类型的数据用于不同的操作,所以最重要的方面是应用程序之间的通信。 当应用程序可以通信时,它们之间的数据共享变得容易。 就像在亚洲运行的应用程序向在欧洲运行的应用程序…

java swing 打开文件_java swing实现打开Excel文件并进行处理

这里选择Excel文件是业务需要,话不多说1、引入对Excel处理的相关依赖org.apache.poipoi3.16org.apache.poipoi-ooxml3.162、进行swing的相关布局代码:package com.mozarta;import org.apache.poi.ss.usermodel.Row;import org.apache.poi.xssf.usermodel…

@ParameterizedTest在@CvsSource中具有空值

在JUnit 4中编写参数化测试非常麻烦。 JUnit 5对框架进行了一些有用的改进,并且使用不同的参数运行相同的测试比以前的版本要简单得多。 但是,在这样的参数中传递空值存在一个小问题。 在这篇文章中,我将向您展示如何在JUnit 5中的Parametrz…

java正则断言_Java正则表达断言篇

正则表达式的先行断言和后行断言一共有4种形式&#xff1a;(?pattern) 零宽正向先行断言(zero-width positive lookahead assertion)(?!pattern) 零宽负向先行断言(zero-width negative lookahead assertion)(?<pattern) 零宽正向后行断言(zero-width positive lookbehin…

java的对象对象映射_Java对象到对象映射器

java的对象对象映射我在该项目上使用了Dozer一段时间。 但是&#xff0c;最近我遇到了一个非常有趣的错误&#xff0c;这促使我环顾四周&#xff0c;并尝试使用其他“对象到对象”映射器。 这是我找到的工具列表&#xff1a; 推土机&#xff1a;推土机是Java Bean到Java Bea…

java parallelstream_关于Java8 parallelStream并发安全的深入讲解

背景Java8的stream接口极大地减少了for循环写法的复杂性&#xff0c;stream提供了map/reduce/collect等一系列聚合接口&#xff0c;还支持并发操作&#xff1a;parallelStream。在爬虫开发过程中&#xff0c;经常会遇到遍历一个很大的集合做重复的操作&#xff0c;这时候如果使…

Jakarta EE,EE4J和Java EE之间的关系

Jakarta EE的名称已经存在了一个多月&#xff0c;即使Mike Milinkovich在他的博客文章“名称是……”中很好地解释了名称和概念&#xff0c;但对于它们之间的关系仍然有些困惑&#xff0c;我也提出了疑问只要有话题就可以围绕它。 我试图在这里总结一下。 希望能帮助到你&#…

java readline 超时_跳过Java中的BufferedReader readLine()方法

是否有一种简单的方法可以跳过java中的readLine()方法(如果它花费的时间超过2秒)&#xff1f;这是我问这个问题的背景&#xff1a;public void run(){boolean looping true;while(looping) {for(int x 0; xtry {Comm s clientList.get(x);String str s.recieve();// code t…

minwindow java_Java经典算法:最小窗口子字符串

给定一个字符串S和一个字符串T&#xff0c;找到S中的最小窗口&#xff0c;其中将包含T中所有字符的复杂度为O(n)。例如&#xff0c;S “ ADOBECODEBANC”&#xff0c;T “ ABC”&#xff0c;最小窗口为“ BANC”。Java解决方案public String minWindow(String s, String t) {Ha…

j2ee可以用于前端开发吗_用于J2EE开发的Cloud IDE

j2ee可以用于前端开发吗随着许多传统软件工具进入云计算&#xff0c;我想看看它们与传统工具的比较。 我的兴趣是J2EE技术​​&#xff0c;并开始寻找一种云服务&#xff0c;该服务使我能够开发&#xff0c;测试和部署J2EE应用程序。 我很快发现&#xff0c;许多云IDE是为Web前…

java为什么全是乱码_java一切乱码的解释 以及源头

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼InputStreamReader in new InputStreamReader(new FileInputStream(“demo.txt”),”UTF-8”);给InputStreamReader指定解码编码&#xff0c;这样二者统一就不会出现乱码了。下面说说字符输出流。字符输出流的原理和字符输入流的原…

JAVA连接数据库ij_Derby 客户端 ij使用

Derby是开源的、嵌入式的Java数据库程序&#xff0c;ij是Derby提供的客户端工具&#xff0c;相当于其他数据库提供的sqlplus工具。ij是纯Java的程序&#xff0c;不用安装&#xff0c;使用起来就像运行普通的Java应用程序一样。接下来说下&#xff1a;如何使用ij工具去操作数据库…

使用Google Cloud Storage托管您的Maven工件

如果您使用Google Cloud并将Java用于项目&#xff0c;那么Google Cloud Storage是托管团队工件的理想场所。 它很容易设置&#xff0c;而且很便宜。 如果您对它们的功能不特别感兴趣&#xff0c;那么它比设置现有存储库选项&#xff08;jfrog&#xff0c;nexus&#xff0c;arc…

java+map对象判断空值_java判断map中是否存在指定对象

Map判断是否包含指定的value使用containsValue方法。(推荐&#xff1a;java视频教程)定义containsValue(Object value) 如果此映射将一个或多个键映射到指定值&#xff0c;则返回 true示例&#xff1a;/**** Map集合判断是否包含value**/public class MapDemo{public static vo…

mysql 主主模式优缺点_mysql主主同步模式

主192.168.56.20 和 从都新建数据库db1 db2 db3(如果数据库在用&#xff0c;需要上锁后手动从主备份&#xff0c;然后在从恢复)mysql> create database db1;Query OK, 1 row affected (0.00 sec)mysql> create database db2;Query OK, 1 row affected (0.00 sec)mysql>…

spring 类型转换器_Spring中的类型转换

spring 类型转换器以下是一些需要类型转换的简单情况&#xff1a; 情况1。 为了帮助简化bean配置&#xff0c;Spring支持属性值与文本值之间的转换。 每个属性编辑器仅设计用于某些类型的属性。 为了使用它们&#xff0c;我们必须在Spring容器中注册它们。 案例2。 同样&…

java+语音识别+谷歌_JAVA使用谷歌语音识别API

我正在尝试使用谷歌语音识别API.这是我写的代码&#xff1a;有用.我从服务器得到答案&#xff1a;{"status":5,"id":"8803471b14a2310dfcf917754e8bd4a7-1","hypotheses":[]}现在的问题是“状态&#xff1a;5”.事实上,这里的状态代码…

java中对象字节数_JAVA中求解对象所占字节大小

该类为cache4j缓存框架中的工具类方法&#xff0c;该方法实现了两个接口接口1&#xff1a;计算对象在内存中所占字节数接口2&#xff1a;复制对象&#xff0c;实现深度克隆效果&#xff0c;实现原理为先序列化对象&#xff0c;然后在反序列化对象&#xff1b;返回一个新的对象&…

excel查重复_毕业季 | 如何降低论文的查重率

毕业季吾日三省吾身实验做完了吗&#xff1f;论文写完了吗&#xff1f;查重能通过吗&#xff1f;学术圈的前辈告诉我们&#xff0c;只有站在巨人的肩膀上才能看得更远。在撰写一篇论文时&#xff0c;为保证质量和可靠性&#xff0c;难免需要引用前人的成果&#xff0c;这也反映…

Sun过去的世界中的JDK 11和代理

使用JDK 11后&#xff0c;就sun.misc.Unsafe的第一种方法。 其中&#xff0c; defineClass方法已删除。 代码生成框架通常使用此方法在现有的类加载器中定义新的类。 尽管此方法易于使用&#xff0c;但它的存在也使JVM本质上不安全&#xff0c;正如其定义类的名称所暗示的那样。…