`

第二篇 多线程的使用——中断线程详解(Interrupt)

    博客分类:
  • Java
阅读更多

 

在上篇文章《多线程的使用——Thread类和Runnable接口》中提到中断线程的问题。在JAVA中,曾经使用stop方法来停止线程,然而,该方法具有固有的不安全性,因而已经被抛弃(Deprecated)。那么应该怎么结束一个进程呢?官方文档中对此有详细说明:《为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?》。在此引用stop方法的说明:

 

1. Why is Thread.stop deprecated?

Because it is inherently unsafe. Stopping a thread causes it to unlock all the monitors that it has locked. (The monitors are unlocked as the ThreadDeath exception propagates up the stack.) If any of the objects previously protected by these monitors were in an inconsistent state, other threads may now view these objects in an inconsistent state. Such objects are said to be damaged. When threads operate on damaged objects, arbitrary behavior can result. This behavior may be subtle and difficult to detect, or it may be pronounced. Unlike other unchecked exceptions, ThreadDeath kills threads silently; thus, the user has no warning that his program may be corrupted. The corruption can manifest itself at any time after the actual damage occurs, even hours or days in the future.

 

大概意思是:

因为该方法本质上是不安全的。停止一个线程将释放它已经锁定的所有监视器(作为沿堆栈向上传播的未检查 ThreadDeath 异常的一个自然后果)。如果以前受这些监视器保护的任何对象都处于一种不一致的状态,则损坏的对象将对其他线程可见,这有可能导致任意的行为。此行为可能是微妙的,难以察觉,也可能是显著的。不像其他的未检查异常,ThreadDeath异常会在后台杀死线程,因此,用户并不会得到警告,提示他的程序可能已损坏。这种损坏有可能在实际破坏发生之后的任何时间表现出来,也有可能在多小时甚至在未来的很多天后。

在文档中还提到,程序员不能通过捕获ThreadDeath异常来修复已破坏的对象。具体原因见原文。

既然stop方法不建议使用,那么应该用什么方法来代理stop已实现相应的功能呢?

 

1、通过修改共享变量来通知目标线程停止运行

 

大部分需要使用stop的地方应该使用这种方法来达到中断线程的目的。

 

这种方法有几个要求或注意事项:

(1)目标线程必须有规律的检查变量,当该变量指示它应该停止运行时,该线程应该按一定的顺序从它执行的方法中返回。

(2)该变量必须定义为volatile,或者所有对它的访问必须同步(synchronized)。

 

例如:

假如你的applet包括start,stop,run几个方法:

 

private Thread blinker;

public void start() {
	blinker = new Thread(this);
	blinker.start();
}

public void stop() {
	blinker.stop();  // UNSAFE!
}

public void run() {
	Thread thisThread = Thread.currentThread();
	while (true) {
		try {
		thisThread.sleep(interval);
		} catch (InterruptedException e){
		}
		repaint();
	}
}

 

你可以使用如下方式避免使用Thread.stop方法:

 

private volatile Thread blinker;

public void stop() {
	blinker = null;
}

public void run() {
	Thread thisThread = Thread.currentThread();
	while (blinker == thisThread) {
		try {
			thisThread.sleep(interval);
		} catch (InterruptedException e){
		}
		repaint();
	}
}

 

 

 

2、通过Thread.interrupt方法中断线程

 

通常情况下,我们应该使用第一种方式来代替Thread.stop方法。然而以下几种方式应该使用Thread.interrupt方法来中断线程(该方法通常也会结合第一种方法使用)。

一开始使用interrupt方法时,会有莫名奇妙的感觉:难道该方法有问题?

API文档上说,该方法用于"Interrupts this thread"。请看下面的例子:

 

package com.polaris.thread;

public class TestThread implements Runnable{

    boolean stop = false;
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(new TestThread(),"My Thread");
        System.out.println( "Starting thread..." );
        thread.start();
        Thread.sleep( 3000 );
        System.out.println( "Interrupting thread..." );
        thread.interrupt();
        System.out.println("线程是否中断:" + thread.isInterrupted());
        Thread.sleep( 3000 );
        System.out.println("Stopping application..." );
    }
    public void run() {
        while(!stop){
            System.out.println( "My Thread is running..." );
            // 让该循环持续一段时间,使上面的话打印次数少点
            long time = System.currentTimeMillis();
            while((System.currentTimeMillis()-time < 1000)) {
            }
        }
        System.out.println("My Thread exiting under request..." );
    }
}

 

 

运行后的结果是:

Starting thread...

My Thread is running...

My Thread is running...

My Thread is running...

My Thread is running...

Interrupting thread...

线程是否中断:true

My Thread is running...

My Thread is running...

My Thread is running...

Stopping application...

My Thread is running...

My Thread is running...

……

应用程序并不会退出,启动的线程没有因为调用interrupt而终止,可是从调用isInterrupted方法返回的结果可以清楚地知道该线程已经中断了。那位什么会出现这种情况呢?到底是interrupt方法出问题了还是isInterrupted方法出问题了?在Thread类中还有一个测试中断状态的方法(静态的)interrupted,换用这个方法测试,得到的结果是一样的。由此似乎应该是interrupt方法出问题了。于是,在网上有一篇文章:《 Java Thread.interrupt 害人! 中断JAVA线程》,它详细的说明了应该如何使用interrupt来中断一个线程的执行。

实际上,在JAVA API文档中对该方法进行了详细的说明。该方法实际上只是设置了一个中断状态,当该线程由于下列原因而受阻时,这个中断状态就起作用了:

(1)如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,或者该类的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法过程中受阻,则其中断状态将被清除,它还将收到一个InterruptedException异常。这个时候,我们可以通过捕获InterruptedException异常来终止线程的执行,具体可以通过return等退出或改变共享变量的值使其退出。

(2)如果该线程在可中断的通道上的 I/O 操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程将收到一个 ClosedByInterruptException。这时候处理方法一样,只是捕获的异常不一样而已。

 

其实对于这些情况有一个通用的处理方法:

 

package com.polaris.thread;

public class TestThread2 implements Runnable{

    boolean stop = false;
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(new TestThread2(),"My Thread2");
        System.out.println( "Starting thread..." );
        thread.start();
        Thread.sleep( 3000 );
        System.out.println( "Interrupting thread..." );
        thread.interrupt();
        System.out.println("线程是否中断:" + thread.isInterrupted());
        Thread.sleep( 3000 );
        System.out.println("Stopping application..." );
    }
    public void run() {
        while(!stop){
            System.out.println( "My Thread is running..." );
            // 让该循环持续一段时间,使上面的话打印次数少点
            long time = System.currentTimeMillis();
            while((System.currentTimeMillis()-time < 1000)) {
            }
            if(Thread.currentThread().isInterrupted()) {
                return;
            }
        }
        System.out.println("My Thread exiting under request..." );
    }
}

 

因为调用interrupt方法后,会设置线程的中断状态,所以,通过监视该状态来达到终止线程的目的。

 

总结:程序应该对线程中断作出恰当的响应。响应方式通常有三种:(来自温绍锦(昵称:温少):http//www.cnblogs.com/jobs/


注意:interrupted与isInterrupted方法的区别(见API文档)

 

 引用一篇文章
来自随心所欲http://redisliu.blog.sohu.com/131647795.html 的Java的interrupt机制

 

当外部线程对某线程调用了thread.interrupt()方法后,java语言的处理机制如下:


如果该线程处在可中断状态下,(调用了xx.wait(),或者Selector.select(),Thread.sleep()等特定会发生阻塞的api),那么该线程会立即被唤醒,同时会受到一个InterruptedException,同时,如果是阻塞在io上,对应的资源会被关闭。如果该线程接下来不执行“Thread.interrupted()方法(不是interrupt),那么该线程处理任何io资源的时候,都会导致这些资源关闭。当然,解决的办法就是调用一下interrupted(),不过这里需要程序员自行根据代码的逻辑来设定,根据自己的需求确认是否可以直接忽略该中断,还是应该马上退出。


如果该线程处在不可中断状态下,就是没有调用上述api,那么java只是设置一下该线程的interrupt状态,其他事情都不会发生,如果该线程之后会调用行数阻塞API,那到时候线程会马会上跳出,并抛出InterruptedException,接下来的事情就跟第一种状况一致了。如果不会调用阻塞API,那么这个线程就会一直执行下去。除非你就是要实现这样的线程,一般高性能的代码中肯定会有wait(),yield()之类出让cpu的函数,不会发生后者的情况。

  • 大小: 33.4 KB
0
0
分享到:
评论

相关推荐

    Java多线程之中断线程(Interrupt)的使用详解

    Java中的多线程允许并发执行多个任务,而中断机制是Java提供的一种优雅地停止线程执行的方式。`Thread.interrupt()`方法是中断线程的主要...正确理解和使用中断机制,可以帮助编写更健壮、更易于维护的多线程应用程序。

    Java多线程详解及示例

    理解多线程的概念,掌握线程的创建、同步、通信、死锁避免等核心知识点,以及合理使用线程池,对于编写高效、稳定的并发程序至关重要。通过实践,开发者可以更好地应对并发编程中的挑战,提升软件的质量和性能。

    Java多线程详解

    以上是对"Java多线程详解"主题的详细阐述,涵盖了Java多线程的基本概念、实现方式、线程控制、线程池、并发集合、线程间通信以及并发编程中常见的问题和解决方案。学习和熟练掌握这些内容对于开发高效的多线程Java...

    C# 多线程编程 详解

    ### C#多线程编程详解 #### 一、引言 在现代软件开发中,多线程编程是一项至关重要的技术,它能够显著提高程序的执行效率和响应速度。《C#多线程编程详解》一书由安德鲁·D·比瑞尔撰写,为读者提供了深入理解并...

    java多线程详解(比较详细的阐述了多线程机制)

    Java多线程还涉及到线程中断和异常处理,Thread类提供了interrupt()方法发起中断请求,线程可以通过检查isInterrupted()或isInterrupted()状态响应中断。在多线程环境中,异常处理也需特别注意,合理的try-catch-...

    java线程中断之interrupt和stop.docx

    在Java多线程编程中,线程控制是至关重要的技术之一。有时我们需要在特定条件下停止某个线程的执行,或者中断正在等待的线程。Java提供了多种方式来实现这些功能,其中`interrupt`和`stop`是最常用的方法。本文将...

    Java多线程详解与多线程实例

    总的来说,Java多线程提供了强大的并发处理能力,通过继承Thread类或实现Runnable接口创建线程,使用同步机制确保线程安全,以及通过中断机制控制线程的生命周期。理解并熟练掌握这些概念对于编写高效、健壮的多线程...

    java多线程设计模式详解

    Java多线程设计模式是Java编程中不可或缺的一部分,它涉及到如何在并发环境下高效、安全地组织代码...阅读提供的"java多线程设计模式详解.pdf"和"Java多线程设计模式源码"文件,将能更深入地理解这些模式的实际运用。

    java多线程中断代码详解

    Java 多线程中断代码详解 Java 中断机制是多线程编程中的一种重要机制。它允许一个线程请求另一个线程停止执行某个操作或退出线程。Java 提供了多种方式来中断线程,包括使用 stop() 方法、interrupt() 方法和使用 ...

    JAVA多线程设计模式详解

    本书“JAVA多线程设计模式详解”深入探讨了这一主题,旨在帮助开发者理解和掌握如何在Java环境中高效地使用多线程。 首先,基础内容介绍涵盖了线程的基本概念,包括进程与线程的区别,线程的创建方式,如通过实现...

    多线程详解(通俗易懂)

    在编程领域,多线程是实现并发执行任务的关键技术,尤其在Java中,它的重要性不言而喻。...学习尚硅谷_宋红康的《第8章_多线程》PDF文档,将有助于你深入理解这些概念和技术,进一步提升你的Java多线程编程能力。

    多线程编程详解

    在IT领域,多线程编程是一项至关重要的技术,特别是在Java这样的多平台开发环境中。本文将深入探讨多线程编程的概念、重要性以及如何在Java中实现。我们将从以下几个方面进行详细讲解: 1. **多线程概念** - **...

    java+多线程+同步详解源代码学习

    Java多线程与同步是Java编程中的核心概念,它们在构建高效、响应迅速的应用程序时起着至关重要的作用。在大型系统开发中,多线程技术使得程序能够同时执行多个任务,提高系统的并发性,而同步机制则确保了在多线程...

    java中的多线程实例详解(自己去运行看结果)

    Java中的多线程是编程领域中的重要概念,尤其在服务器端和高性能应用中不可或缺。它允许程序同时执行多个任务,从而提高系统效率和响应性。本文将深入探讨Java多线程的实例,帮助读者理解其工作原理和实际应用。 ...

    Java多线程编程详解

    Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程的实现...通过阅读《Java多线程编程详解》这本书,你可以进一步了解和提升这方面的技能。

    Java多线程编程深入详解

    标题《Java多线程编程深入详解》所涉及的知识点涵盖了Java多线程编程的核心思想、原理以及在实际开发中可能遇到的问题和解决方案。以下是对这些知识点的详细阐述: 1. 多进程与多线程概念的区分和理解 - 进程是...

    java多线程编程详解

    在"JAVA多线程编程详解-详细操作例子.doc"和"Java多线程编程详解.doc"文档中,你应该能找到关于以上知识点的具体示例和深入解释,包括如何创建线程、线程间的通信(如wait/notify机制、Semaphore、CountDownLatch)...

    Java多线程的用法详解

    Java多线程是编程中一个重要的概念,特别是在开发高并发、高性能的应用程序时不可或缺。本文将详细解析Java中实现多线程的两种主要方式以及线程的生命周期。 1. 创建线程 在Java中,创建线程主要有两种方法: **...

    Java 多线程编程详解.pdf

    总之,《Java多线程编程详解》这份PDF文档全面覆盖了Java多线程编程的核心内容,无论你是初学者还是有经验的开发者,都能从中受益。通过学习,你可以更好地理解和掌握如何在Java中有效地利用多线程,提升程序的性能...

Global site tag (gtag.js) - Google Analytics