当前位置:七道奇文章资讯编程技术Java编程
日期: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编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
  • 利用Javascript实现网页水印(非图片水印)
  • Java开辟环境的搭建
  • Ubuntu java安装与配置
  • 办理Ubuntu 10.04 Firefox3.6 Java浏览器插件不工作的问
  • Ubuntu重装后Java环境的设置
  • Sun Java进入Ubuntu 10.10软件中央
  • Ubuntu 10.10配置Java开辟环境
  • 在Ubuntu 10.10中配置Java环境变量的办法
  • Ubuntu下Java环境的搭建
  • Ubuntu 10.04 下安装 Java, JRE
  • Ubuntu 10.04下的搭建SUN JAVA开辟环境
  • Ubuntu 12.04安装java7
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .