日期:2011-03-22 16:16:00 来源:本站整理
java的线程死锁[Java编程]
本文“java的线程死锁[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
由于线程大概进入堵塞状况,并且由于对象大概拥有“同步”办法——除非同步锁定被解除,不然线程不能拜候那个对象——所以一个线程完好大概等候另一个对象,而另一个对象又在等候下一个对象,以此类推.这个“等候”链最可怕的情形就是进入封闭状况——最后那个对象等候的是第一个对象!此时,全部线程城市陷入无停止的彼此等候状况,大家都动弹不得.我们将这种情形称为“死锁”.固然这种情形并非常常呈现,但一旦碰到,程序的调试将变得非常艰难.
就语言本身来说,还没有直接供应避免死锁的帮忙办法,需求我们通过谨严的计划来避免.假若有谁需求调试一个死锁的程序,他是没有任何诀窍可用的.
1. Java 1.2对stop(),suspend(),resume()以及destroy()的反对
为削减呈现死锁的大概,Java 1.2作出的一项奉献是“反对”利用Thread的stop(),suspend(),resume()以及destroy()办法.
之所以反对利用stop(),是因为它不安全.它会解除由线程获得的全部锁定,并且假如对象处于一种不联贯状况(“被破坏”),那么其他线程能在那种状况下查抄和改正它们.后果便造成了一种奇妙的局面,我们很难查抄出真正的问题所在.所以应尽大概避免利用stop(),应当采取Blocking.java那样的办法,用一个标志奉告线程什么时刻通过退出自己的run()办法来中止自己的履行.
假如一个线程被堵塞,比方在它等候输入的时刻,那么普通都不能象在Blocking.java中那样轮询一个标志.但在这些情形下,我们仍旧不该利用stop(),而应换用由Thread供应的interrupt()办法,以便中止并退出堵塞的代码.
//: Interrupt.java // The alternative approach to using stop() // when a thread is blocked import java.awt.*; import java.awt.event.*; import java.applet.*; class Blocked extends Thread { public synchronized void run() { try { wait(); // Blocks } catch(InterruptedException e) { System.out.println("InterruptedException"); } System.out.println("Exiting run()"); } } public class Interrupt extends Applet { private Button interrupt = new Button("Interrupt"); private Blocked blocked = new Blocked(); public void init() { add(interrupt); interrupt.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println("Button pressed"); if(blocked == null) return; Thread remove = blocked; blocked = null; // to release it remove.interrupt(); } }); blocked.start(); } public static void main(String[] args) { Interrupt applet = new Interrupt(); Frame aFrame = new Frame("Interrupt"); aFrame.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); aFrame.add(applet, BorderLayout.CENTER); aFrame.setSize(200,100); applet.init(); applet.start(); aFrame.setVisible(true); } } ///:~
Blocked.run()内部的wait()会产生堵塞的线程.当我们按下按钮今后,blocked(堵塞)的句柄就会设为null,使垃圾汇集器可以将其排除,然后调用对象的interrupt()办法.假如是初次按下按钮,我们会看到线程正常退出.但在没有可供“杀死”的线程今后,看到的便只是按钮被按下罢了.
suspend()和resume()办法天生简单发死活锁.调用suspend()的时刻,目标线程会停下来,但却仍旧持有在这之前得到的锁定.此时,其他任何线程都不能拜候锁定的资源,除非被“挂起”的线程恢复运行.对任何线程来说,假如它们想恢复目标线程,同时又试牟利用任何一个锁定的资源,就会造成令人尴尬的死锁.所以我们不该该利用suspend()和resume(),而应在自己的Thread类中置入一个标志,指出线程应当活动还是挂起.若标志指出线程应当挂起,便用wait()命其进入等候状况.若标志指出线程该当恢复,则用一个notify()重新启动线程.我们可以改正前面的Counter2.java来实际体验一番.固然两个版本的效果是差不多的,但大家会注意到代码的组织构造发生了很大的改变——为全部“听众”都利用了匿名的内部类,并且Thread是一个内部类.这使得程序的编写略微便利一些,因为它撤消了Counter2.java中一些额外的记录工作.
//: Suspend.java // The alternative approach to using suspend() // and resume(), which have been deprecated // in Java 1.2. import java.awt.*; import java.awt.event.*; import java.applet.*; public class Suspend extends Applet { private TextField t = new TextField(10); private Button suspend = new Button("Suspend"), resume = new Button("Resume"); class Suspendable extends Thread { private int count = 0; private boolean suspended = false; public Suspendable() { start(); } public void fauxSuspend() { suspended = true; } public synchronized void fauxResume() { suspended = false; notify(); } public void run() { while (true) { try { sleep(100); synchronized(this) { while(suspended) wait(); } } catch (InterruptedException e){} t.setText(Integer.toString(count++)); } } } private Suspendable ss = new Suspendable(); public void init() { add(t); suspend.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { ss.fauxSuspend(); } }); add(suspend); resume.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { ss.fauxResume(); } }); add(resume); } public static void main(String[] args) { Suspend applet = new Suspend(); Frame aFrame = new Frame("Suspend"); aFrame.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e){ System.exit(0); } }); aFrame.add(applet, BorderLayout.CENTER); aFrame.setSize(300,100); applet.init(); applet.start(); aFrame.setVisible(true); } } ///:~
Suspendable中的suspended(已挂起)标志用于开关“挂起”大概“暂停”状况.为挂起一个线程,只需调用fauxSuspend()将标志设为true(真)便可.对标志状况的侦测是在run()内举行的.就象本章早些时刻提到的那样,wait()必须设为“同步”(synchronized),使其可以利用对象锁.在fauxResume()中,suspended标志被设为false(假),并调用notify()——由于这会在一个“同步”从句中唤醒wait(),所以fauxResume()办法也必须同步,使其能在调用notify()之前获得对象锁(这样一来,对象锁可由要唤醍的那个wait()利用).假如遵循本程序展示的款式,可以避免利用wait()和notify().
Thread的destroy()办法根本没有实现;它近似一个根本不能恢复的suspend(),所以会发生与suspend()一样的死锁问题.但是,这一办法没有得到明确的“反对”,大概会在Java今后的版本(1.2版今后)实现,用于一些可以承受死锁危险的特别场所.
大家大概会奇特当初为什么要实现这些目前又被“反对”的办法.之所以会呈现这种情形,大约是由于Sun公司主要让技术人员来决意对语言的窜改,而不是那些市场贩卖人员.普通,技术人员比搞贩卖的更能理解语言的实质.当初犯下了错误今后,也能较为明智地正视它们.这意味着Java可以持续进步,即便这使Java程序员多少感到有些不便.就我自己来说,甘愿面对这些不便之处,也不肯看到语言阻滞不前.
以上是“java的线程死锁[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |
- ·上一篇文章:线程的优先级
- ·下一篇文章:<b>java数据报编程</b>
- ·中查找“java的线程死锁”更多相关内容
- ·中查找“java的线程死锁”更多相关内容
评论内容只代表网友观点,与本站立场无关!
评论摘要(共 0 条,得分 0 分,平均 0 分)
查看完整评论