欢迎来到天天文库
浏览记录
ID:37768455
大小:26.33 KB
页数:6页
时间:2019-05-30
《为何不赞成使用Thread.stopsuspend和resume》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、为什么Thread.stop被废弃了?因为其天生是不安全的。停止一个线程会导致其解锁其上被锁定的所有监视器(监视器以在栈顶产生ThreadDeath异常的方式被解锁)。如果之前被这些监视器保护的任何对象处于不一致状态,其它线程看到的这些对象就会处于不一致状态。这种对象被称为受损的(damaged)。当线程在受损的对象上进行操作时,会导致任意行为。这种行为可能微妙且难以检测,也可能会比较明显。不像其他未受检的(unchecked)异常,ThreadDeath悄无声息的杀死及其他线程。因此,用户得不到
2、程序可能会崩溃的警告。崩溃会在真正破坏发生后的任意时刻显现,甚至在数小时或数天之后。难道我不能仅捕获ThreadDeath异常来修正受损对象吗?理论上,也许可以,但书写正确的多线程代码的任务将极其复杂。由于两方面的原因,这一任务的将几乎不可能完成:··线程可以在几乎任何地方抛出ThreadDeath异常。由于这一点,所有的同步方法和(代码)块将必须被考虑得事无巨细。·线程在清理第一个ThreadDeath异常的时候(在catch或finally语句中),可能会抛出第二个。清理工作将不得不重复直到到
3、其成功。保障这一点的代码将会很复杂。Thread.stop(Throwable)会有什么问题?除了上述所有问题外,此方法还可能产生其目标线程不准备处理的异常(包括若非为实现此方法,线程不太可能抛出的受检异常)。例如,下面的方法行为上等同于Java的throw操作,但是绕开了编译器的努力,即保证要调用的方法已经声明了其所有可能抛出的异常:staticvoidsneakyThrow(Throwablet){Thread.currentThread().stop(t);}我应该用什么来取代Thread.
4、stop?大多数stop的使用,应当被替换为简单修改某些变量来指示其目标线程将停止运行的代码。目标线程应当有规律的检查这些变量。并且,如果这些变量指示其将停止运行,目标线程应当以某种有序的方式从它的run方法返回(这正是JavaTutorial一贯建议的方式)。为了确保停止请求的及时传达,变量必须是volatile的(或者变量的访问被同步)。例如,假设你的applet包含了start、stop和run方法:privateThreadblinker;publicvoidstart(){blinker
5、=newThread(this);blinker.start();}publicvoidstop(){blinker.stop();//UNSAFE!}publicvoidrun(){ThreadthisThread=Thread.currentThread();while(true){try{thisThread.sleep(interval);}catch(InterruptedExceptione){}repaint();}}为了避免使用Thread.stop,你可以把applet的stop
6、和run方法替换成:privatevolatileThreadblinker;publicvoidstop(){blinker=null;}publicvoidrun(){ThreadthisThread=Thread.currentThread();while(blinker==thisThread){try{thisThread.sleep(interval);}catch(InterruptedExceptione){}repaint();}}我如何才能停止一个长时间等待的线程(例如,用于输
7、入)?这正是Thread.interrupt方法要做的。与上述相同的“基于状态”的信号传递机制可以被应用,但是状态传递(blinker=null,在上一个例子中)后面可以跟一个Thread.interrupt调用,用来中断和等待:publicvoidstop(){Threadmoribund=waiter;waiter=null;moribund.interrupt();}为了让这种技术起作用,关键在于,对于任何捕获了中断异常但不准备立即处理的方法,应重新断言异常。我们说重新断言(reassert
8、s)而不是重新抛出(rethorws),因为要重新抛出异常并非总是可行。如果捕获InterruptedException的方法没有被声明为抛出这种(受检)异常,那么它应该采用下述咒语来“重新中断自己”:Thread.currentThread().interrupt();如果线程没有响应Thread.interrupt会怎么样?在某些情况下,你可以采取特定于应用的技巧。例如,如果线程在一个已知的socket上等待,你可以关闭这个socket,来促使线程立即返回。不幸的是,确实没有放
此文档下载收益归作者所有