Java如何中断一个正在运行的线程

  程序是很简易的 然而 在编程人员面前 多线程呈现出了一组新的难题 如果没有被恰当的解决 将导致意外的行为以及细微的 难以发现的错误

  在本篇文章中 我们针对这些难题之一 如何中断一个正在运行的线程

  背景中断(Interrupt)一个线程意味着在该线程完成任务之前停止其正在进行的一切 有效地中止其当前的操作 线程是死亡 还是等待新的任务或是继续运行至下一步 就取决于这个程序 虽然初次看来它可能显得简单 但是 你必须进行一些预警以实现期望的结果 你最好还是牢记以下的几点告诫

  首先 忘掉Thread stop方法 虽然它确实停止了一个正在运行的线程 然而 这种方法是不安全也是不受提倡的 这意味着 在未来的JAVA版本中 它将不复存在

  一些轻率的家伙可能被另一种方法Thread interrupt所迷惑 尽管 其名称似乎在暗示著什么 然而 这种方法并不会中断一个正在运行的线程(待会将进一步说明) 正如Listing A中描述的那样 它创建了一个线程 并且试图使用Thread interrupt方法停止该线程 Thread sleep()方法的调用 为线程的初始化和中止提供了充裕的时间 线程本身并不参与任何有用的操作

   class Example extends Thread {            boolean stop=false;            public static void main( String args[] ) throws Exception {            Example thread = new Example ();            System out println( Starting thread );            thread start();            Thread sleep( );            System out println( Interrupting thread );            thread interrupt();            Thread sleep( );            System out println( Stopping application );            //System exit( );            }            public void run() {            while(!stop){            System out println( Thread is running );            long time = System currentTimeMillis();            while((System currentTimeMillis() time < )) {            }            }            System out println( Thread exiting under request );            }            }

  如果你运行了Listing A中的代码 你将在控制台看到以下输出

   Starting thread Thread is running Thread is running Thread is running Interrupting thread Thread is running Thread is running Thread is running Stopping application Thread is running Thread is running Thread is running

  甚至 在Thread interrupt()被调用后 线程仍然继续运行

  真正地中断一个线程

  中断线程最好的 最受推荐的方式是 使用共享变量(shared variable)发出信号 告诉线程必须停止正在运行的任务 线程必须周期性的核查这一变量(尤其在冗余操作期间) 然后有秩序地中止任务 Listing B描述了这一方式

   Listing Bclass Example  extends Thread {  volatile boolean stop = false;  public static void main( String args[] ) throws Exception {    Example  thread = new Example ();   System out println(  Starting thread  );   thread start();   Thread sleep(   );   System out println(  Asking thread to stop  );   thread stop = true;   Thread sleep(   );   System out println(  Stopping application  );   //System exit(   );  }  public void run() {    while ( !stop ) {     System out println(  Thread is running  );      long time = System currentTimeMillis();      while ( (System currentTimeMillis() time <  ) && (!stop) ) {      }    }   System out println(  Thread exiting under request  );  }}

  运行Listing B中的代码将产生如下输出(注意线程是如何有秩序的退出的)

   Starting thread Thread is running Thread is running Thread is running Asking thread to stop Thread exiting under request Stopping application

  虽然该方法要求一些编码 但并不难实现 同时 它给予线程机会进行必要的清理工作 这在任何一个多线程应用程序中都是绝对需要的 请确认将共享变量定义成volatile 类型或将对它的一切访问封入同步的块/方法(synchronized blocks/methods)中

  到目前为止一切顺利!但是 当线程等待某些事件发生而被阻塞 又会发生什么?当然 如果线程被阻塞 它便不能核查共享变量 也就不能停止 这在许多情况下会发生 例如调用Object wait() ServerSocket accept()和DatagramSocket receive()时 这里仅举出一些

  他们都可能永久的阻塞线程 即使发生超时 在超时期满之前持续等待也是不可行和不适当的 所以 要使用某种机制使得线程更早地退出被阻塞的状态

  很不幸运 不存在这样一种机制对所有的情况都适用 但是 根据情况不同却可以使用特定的技术 在下面的环节 我将解答一下最普遍的例子

  使用Thread interrupt()中断线程

  正如Listing A中所描述的 Thread interrupt()方法不会中断一个正在运行的线程 这一方法实际上完成的是 在线程受到阻塞时抛出一个中断信号 这样线程就得以退出阻塞的状态 更确切的说 如果线程被Object wait Thread join和 Thread sleep三种方法之一阻塞 那么 它将接收到一个中断异常(InterruptedException) 从而提早地终结被阻塞状态

  因此 如果线程被上述几种方法阻塞 正确的停止线程方式是设置共享变量 并调用interrupt()(注意变量应该先设置) 如果线程没有被阻塞 这时调用interrupt()将不起作用 否则 线程就将得到异常(该线程必须事先预备好处理此状况) 接着逃离阻塞状态 在任何一种情况中 最后线程都将检查共享变量然后再停止 Listing C这个示例描述了该技术

   Listing Cclass Example  extends Thread {  volatile boolean stop = false;  public static void main( String args[] ) throws Exception {   Example  thread = new Example ();   System out println(  Starting thread  );   thread start();   Thread sleep(   );   System out println(  Asking thread to stop  );   thread stop = true;//如果线程阻塞 将不会检查此变量   thread interrupt();   Thread sleep(   );   System out println(  Stopping application  );   //System exit(   );  }  public void run() {    while ( !stop ) {     System out println(  Thread running  );      try {      Thread sleep(   );      } catch ( InterruptedException e ) {      System out println(  Thread interrupted  );      }    }   System out println(  Thread exiting under request  );  }}

  一旦Listing C中的Thread interrupt()被调用 线程便收到一个异常 于是逃离了阻塞状态并确定应该停止 运行以上代码将得到下面的输出

   Starting thread Thread running Thread running Thread running Asking thread to stop Thread interrupted Thread exiting under request Stopping application

   中断I/O操作

  然而 如果线程在I/O操作进行时被阻塞 又会如何?I/O操作可以阻塞线程一段相当长的时间 特别是牵扯到网络应用时 例如 服务器可能需要等待一个请求(request) 又或者 一个网络应用程序可能要等待远端主机的响应

  如果你正使用通道(channels)(这是在Java 中引入的新的I/O API) 那么被阻塞的线程将收到一个 ClosedByInterruptException异常 如果情况是这样 其代码的逻辑和第三个例子中的是一样的 只是异常不同而已

  但是 你可能正使用Java 之前就存在的传统的I/O 而且要求更多的工作 既然这样 Thread interrupt()将不起作用 因为线程将不会退出被阻塞状态 Listing D描述了这一行为 尽管interrupt()被调用 线程也不会退出被阻塞状态

   Listing Dimport java io *;class Example  extends Thread {  public static void main( String args[] ) throws Exception {    Example  thread = new Example ();   System out println(  Starting thread  );   thread start();   Thread sleep(   );   System out println(  Interrupting thread  );   thread interrupt();   Thread sleep(   );   System out println(  Stopping application  );   //System exit(   );  }  public void run() {   ServerSocket socket;    try {      socket = new ServerSocket( );    } catch ( IOException e ) {     System out println(  Could not create the socket  );      return;    }    while ( true ) {     System out println(  Waiting for connection  );      try {       Socket sock = socket accept();      } catch ( IOException e ) {      System out println(  accept() failed or interrupted  );      }    }  }}

  很幸运 Java平台为这种情形提供了一项解决方案 即调用阻塞该线程的套接字的close()方法 在这种情形下 如果线程被I/O操作阻塞 该线程将接收到一个SocketException异常 这与使用interrupt()方法引起一个InterruptedException异常被抛出非常相似

  唯一要说明的是 必须存在socket的引用(reference) 只有这样close()方法才能被调用 这意味着socket对象必须被共享 Listing E描述了这一情形 运行逻辑和以前的示例是相同的

   Listing Eimport  *;import java io *;class Example  extends Thread {  volatile boolean stop = false;  volatile ServerSocket socket;  public static void main( String args[] ) throws Exception {    Example  thread = new Example ();   System out println(  Starting thread  );   thread start();   Thread sleep(   );   System out println(  Asking thread to stop  );   thread stop = true;   thread socket close();   Thread sleep(   );   System out println(  Stopping application  );   //System exit(   );  }  public void run() {    try {      socket = new ServerSocket( );    } catch ( IOException e ) {     System out println(  Could not create the socket  );      return;    }    while ( !stop ) {     System out println(  Waiting for connection  );      try {       Socket sock = socket accept();      } catch ( IOException e ) {      System out println(  accept() failed or interrupted  );      }    }   System out println(  Thread exiting under request  );  }}

  以下是运行Listing E中代码后的输出

   Starting thread Waiting for connection Asking thread to stop accept() failed or interrupted Thread exiting under request Stopping application

    多线程是一个强大的工具 然而它正呈现出一系列难题 其中之一是如何中断一个正在运行的线程 如果恰当地实现 使用上述技术中断线程将比使用Java平台上已经提供的内嵌操作更为简单 lishixinzhi/Article/program/Java/gj/201311/27481



  • java鎬庢牱鍦鏂扮嚎绋嬪紑濮嬫椂鍋滄姝e湪杩愯鐨绾跨▼
    绛旓細棣栧厛鍛婅瘔浣犵嚎绋嬬殑瀹夊叏鍏抽棴涓鑸湁杩欎箞鍑犵鏂规硶锛涓涓鏄缃杩愯鏍囪閲忥紝濡 boolean running = true;Thread t = new Thread(new Runnable(){ public void run() { while(running) { // } } };閭d箞浣犺繖涓緥瀛愪篃鍙互绫讳技鐨勪负鎸夐挳a涓婄殑绾跨▼娣诲姞涓涓叏灞杩愯鏍囧織閲弐unning锛屽垵鍊间负true銆鍦鐐瑰嚮鎸夐挳b鐨...
  • JAVA 濡備綍鍋滄涓涓繍琛鐫鐨勬寚瀹氱嚎绋
    绛旓細浣犳妸婀栧崡浜虹殑鏍囧織鏀逛簡骞朵笉浼氬奖鍝嶅埌婀栧寳浜猴紒 铏界劧浠栦滑閮鍦鍚屼竴涓伐鍦颁笂骞插悓鏍风殑娲伙紝铏界劧瀹冧滑閮芥槸濡堢敓鐨 鎵浠ユ湰渚嬩腑锛孨澶氫釜绾跨▼瀵硅薄鐢熸垚锛屽苟鍚姩鍚涓涓竴涓閮芥槸鍗曠嫭鐨勫璞★紝鍦ㄥ崟鐙殑杩愯绌洪棿閲岃窇銆傝〃闈笂鐪嬭捣鏉ユ槸鐩稿悓鐨勪换鍔★紝鍏跺疄鏄笉鐩稿悓鐨 boolean runflag=true; 杩欎釜鏍囧織姣忎釜瀵硅薄閮鏈変竴涓锛屼綘鏀瑰彉...
  • java鎬庝箞寮哄埗鍏抽棴涓涓鍦ㄨ繍琛岀殑绾跨▼
    绛旓細); t.start(); Thread.sleep(3000); System.out.println("System is ready to stop thread"); //绾跨▼娌℃湁澶勪簬闃诲鐘舵侊紝璋冪敤绾跨▼瀵瑰簲鐨刬nterrupt()涓嶈兘璁杩愯鐨绾跨▼鍋滄涓嬫潵 t.interrupt();
  • 姹傚姪:java,鎬庢牱浠g爜瀹炵幇缁撴潫姝e湪杩愯鐨绋嬪簭?
    绛旓細System.exit(0);缁堟铏氭嫙鏈猴紒
  • java濡備綍鍋滄涓涓wait鐨勭嚎绋
    绛旓細java.lang.System绫籹tatic void exit(int status) 缁堟褰撳墠姝e湪杩愯鐨 Java 铏氭嫙鏈恒
  • 濡備綍浼橀泤鍦扮粨鏉涓涓绾跨▼?
    绛旓細浣跨敤鏍囧織 涓柇绾跨▼銆1.浣跨敤鏍囧織 涓绉嶇畝鍗曠殑鏂规硶鏄娇鐢ㄧ嚎绋嬫潵鎸囩ず绾跨▼鏄惁姝e湪杩愯锛屽苟浣跨敤姝ゆ爣蹇楁牴鎹偍鐨勮姹傞噰鍙栫籂姝f帾鏂斤紝涓嬮潰鏄涓涓绀轰緥浠g爜锛屾杩颁簡濡備綍浣跨敤鏍囧織鏉ユ潃姝Java绾跨▼銆傚湪涓婇潰鐨勪緥瀛愪腑銆傛垜浠彲浠ラ氳繃灏嗚繍琛屽彉閲忚缃负false鏉ユ帶鍒舵墽琛屻傚湪鎴戜滑鐨勭ず渚嬩腑锛屾垜浠娇鐢ˋtomicBoolean浜嗗苟鍙戯紝濡傛灉鎮ㄤ笉鎯充娇鐢...
  • 濡備綍鍏抽棴java frame杩涚▼
    绛旓細鍏充簬EXIT_ON_CLOSE鐨勮鏄庯細EXIT_ON_CLOSE锛堝湪 JFrame 涓畾涔夛級锛氫娇鐢 System exit 鏂规硶閫鍑哄簲鐢ㄧ▼搴忋備粎鍦ㄥ簲鐢ㄧ▼搴忎腑浣跨敤銆俻ublic void exit(int status)閫氳繃鍚姩铏氭嫙鏈虹殑鍏抽棴搴忓垪锛岀粓姝㈠綋鍓姝e湪杩愯鐨 Java 铏氭嫙鏈恒傛鏂规硶浠庝笉姝e父杩斿洖銆傚彲浠ュ皢鍙橀噺浣滀负涓涓鐘舵佺爜锛涙牴鎹儻渚嬶紝闈為浂鐨勭姸鎬佺爜琛ㄧず闈炴甯...
  • ...bat杩愯杩囩▼涓,濡備綍鐢java鍏抽棴褰撳墠姝e湪杩愯鐨cmd绐楀彛?
    绛旓細绗竴绉 process.destroy();绗簩绉 妯℃嫙杈撳嚭涓涓exit鍛戒护鍒版帶鍒跺彴,灏遍鍑轰簡
  • eclipse鎬庝箞鏍峰仠姝㈢▼搴忕殑杩愯
    绛旓細涓昏惀:鏁欒偛鍩硅-JAVA鍩硅-澶ф暟鎹煿璁-Html5鍩硅-UI鍩硅-python鍩硅绛 鍚慣A鎻愰棶 鍏朵粬鍥炵瓟 浣犲彲浠ョ敤ctrl+c鍋滄鍟婃垨鑰呯偣鍑讳笅闈㈡帶鍒跺彴閭i噷鏈変釜绾㈣壊鐨勫洓鏂瑰舰鐨勬寜閽,閭d釜涔熸槸鍋滄鐨勩傛垨鑰匵X閭d篃鏄 鏈洖绛旇鎻愰棶鑰呴噰绾 浼戞绗y2 | 鍙戝竷浜2010-01-01 涓炬姤| 璇勮(7) 33 5 绋嬪簭杩愯鏃鍦鐣岄潰涓婁細鏈変竴涓绾㈢偣,鐐...
  • java 鐢ㄤ唬鐮濡備綍鍏抽棴绯荤粺姝e湪杩愯鐨excel鏂囦欢
    绛旓細鍦鍐欏叆鏃舵崟鎹夊紓甯搞Java鍒ゆ柇涓嶅嚭鏂囦欢鏄惁鎵撳紑銆備篃娌℃湁寮鸿鍏抽棴鐨勬柟娉曘傚彲浠ュ叧鎺夎繘绋嬨備絾杩樻秹鍙奺xcel鏂囦欢鏄惁淇濆瓨鐨勯棶棰樸傛墍浠ヨ繕鏄彁鍑涓涓鍙嬪ソ娑堟伅銆傝鐢ㄦ埛鑷繁澶勭悊姣旇緝濂姐
  • 扩展阅读:为什么java安装向导被中断 ... java运行的三个步骤 ... java运行不出来怎么回事 ... javac在cmd运行错误 ... java安装了运行不了 ... java底部的运行框没了 ... 一个初中生学java要多久 ... java安装后怎么运行 ... 安装java显示向导被中断 ...

    本站交流只代表网友个人观点,与本站立场无关
    欢迎反馈与建议,请联系电邮
    2024© 车视网