程序是很简易的。然而,在编程人员面前,多线程呈现出了一组新的难题,如果没有被恰当的解决,将导致意外的行为以及细微的,难以发现的错误。
在本篇文章中,我们针对这些难题之一:如何中断一个正在运行的线程。
,,,中断(打断)一个线程意味着在该线程完成任务之前停止其正在进行的一切,有效地中止其当前的操作。线程是死亡,还是等待新的任务或是继续运行至下一步,就取决于这个程序。虽然初次看来它可能显得简单,但是,你必须进行一些预警以实现期望的结果。你最好还是牢记以下的几点告诫。
,,,首先,忘掉Thread.stop方法,虽然它确实停止了一个正在运行的线程,然而,这种方法是不安全也是不受提倡的,这意味着,在未来的Java版本中,它将不复存在。
,,,一些轻率的家伙可能被另一种方法Thread.interrupt所迷惑。尽管,其名称似乎在暗示着什么,然而,这种方法并不会中断一个正在运行的线程(待会将进一步说明),正如清单一个中描述的那样。它创建了一个线程,并且试图使用Thread.interrupt方法停止该线程.Thread.sleep()方法的调用,为线程的初始化和中止提供了充裕的时间。线程本身并不参与任何有用的操作。
清单A
类例二延伸线程{ 布尔停止=false; 公共静态void main (String参数[]){抛出异常 例二线=new例二(); 系统。println(“线程开始……”); thread.start (); 线程。睡眠(3000); 系统。println(“中断线程……”); thread.interrupt (); 线程。睡眠(3000); 系统。println(“停止应用程序……”);//system . exit (0); } 公共空间run () { 而(停止){ 系统。println(“线程正在运行……”); 长时间=System.currentTimeMillis (); 而(System.currentTimeMillis () - & lt;1000)){ } } 系统。println(“线程退出请求……”); } }
如果你运行清单一个中了的代码,你将在控制台看到以下输出:
启动线程…
线程正在运行…
线程正在运行…
线程正在运行…
中断线程…
线程正在运行…
线程正在运行…
线程正在运行…
停止应用程序…
线程正在运行…
线程正在运行…
线程正在运行…
...............................
甚至,在Thread.interrupt()被调用后,线程仍然继续运行。
,,,中断线程最好的,最受推荐的方式是,使用共享变量(共享变量)发出信号,告诉线程必须停止正在运行的任务。线程必须周期性的核查这一变量(尤其在冗余操作期间),然后有秩序地中止任务.Listing B描述了这一方式。
清单B
类Example2扩展线程{ 不稳定的布尔停止=false; 公共静态void main (String参数[]){抛出异常 Example2线程=new Example2 (); 系统。println(“线程开始……”); thread.start (); 线程。睡眠(3000); 系统。println(“问线程停止……”); 线程。停止=true; 线程。睡眠(3000); 系统。println(“停止应用程序……”);//系统。退出(0); } 公共空间run () { 而(停止){ 系统。println(“线程正在运行……”); 长时间=System.currentTimeMillis (); 而(System.currentTimeMillis () - & lt;1000),,(停止)){ } } 系统。println(“线程退出请求……”); } }清单B
运行中的代码将产生如下输出(注意线程是如何有秩序的退出的)
启动线程…
线程正在运行…
线程正在运行…
线程正在运行…
要求线程停止……
线程退出请求下……
停止应用程序…
,,虽然该方法要求一些编码,但并不难实现。同时,它给予线程机会进行必要的清理工作,这在任何一个多线程应用程序中都是绝对需要的。请确认将共享变量定义成挥发性类型或将对它的一切访问封入同步的块/方法(synchronized块/方法)中。
到目前为止一切顺利!但是,当线程等待某些事件发生而被阻塞,又会发生什么?当然,如果线程被阻塞,它便不能核查共享变量,也就不能停止。这在许多情况下会发生,例如调用Object.wait (), ServerSocket.accept()和DatagramSocket.receive()时,这里仅举出一些。