Java Thread.interrupt 害人! 中断JAVA线程(zz)
http://www.blogjava.net/jinfeng_wang/archive/2012/04/22/196477.html#376322
——————————————————————————————————————————————————————————
程序是很简易的。然而,在编程人员面前,多线程呈现出了一组新的难题,如果没有被恰当的解决,将导致意外的行为以及细微的、难以发现的错误。 在本篇文章中,我们针对这些难题之一:如何中断一个正在运行的线程。 背景 中断(Interrupt)一个线程意味着在该线程完成任务之前停止其正在进行的一切,有效地中止其当前的操作。线程是死亡、还是等待新的任务或 是继续运行至下一步,就取决于这个程序。虽然初次看来它可能显得简单,但是,你必须进行一些预警以实现期望的结果。你最好还是牢记以下的几点告诫。 首先,忘掉Thread.stop方法。虽然它确实停止了一个正在运行的线程,然而,这种方法是不安全也是不受提倡的,这意味着,在未来的JAVA版本中,它将不复存在。 |
|
一些轻率的家伙可能被另一种方法Thread.interrupt所迷惑。尽管,其名称似乎在暗示着什么,然而,这种方法并不会中断一个正在运行 的线程(待会将进一步说明),正如Listing A中描述的那样。它创建了一个线程,并且试图使用Thread.interrupt方法停止该线程。 Thread.sleep()方法的调用,为线程的初始化和中止提供了充裕的时间。线程本身并不参与任何有用的操作。 class Example1 extends Thread { boolean stop=false; public static void main( String args[] ) throws Exception { Example1 thread = new Example1(); System.out.println( "Starting thread..." ); thread.start(); Thread.sleep( 3000 ); System.out.println( "Interrupting thread..." ); thread.interrupt(); Thread.sleep( 3000 ); System.out.println("Stopping application..." ); //System.exit(0); } public void run() { while(!stop){ System.out.println( "Thread is running..." ); long time = System.currentTimeMillis(); while((System.currentTimeMillis()-time < 1000)) { } } System.out.println("Thread exiting under request..." ); } } 如果你运行了Listing A中的代码,你将在控制台看到以下输出: |
============================================
Writing multithreaded programs in Java, with its built-in support for
threads, is fairly straightforward. However, multithreading presents a
whole set of new challenges to the programmer that, if not correctly
addressed, can lead to unexpected behavior and subtle, hard-to-find
errors. In this article, we address one of those challenges: how to
interrupt a running thread.
Background
Interrupting a thread means stopping what it is doing before it has
completed its task, effectively aborting its current operation. Whether
the thread dies, waits for new tasks, or goes on to the next step
depends on the application.
Although it may seem simple at first, you must take some precautions in
order to achieve the desired result. There are some caveats you must be
aware of as well.
First of all, forget the Thread.stop method. Although it indeed stops a running thread, the method is unsafe and was deprecated, which means it may not be available in future versions of the Java.
Another method that can be confusing for the unadvised is Thread.interrupt. Despite what its name may imply, the method does not interrupt a running thread (more on this later), as Listing A demonstrates. It creates a thread and tries to stop it using Thread.interrupt. The calls to Thread.sleep() give plenty of time for the thread initialization and termination. The thread itself does not do anything useful.
If you run the code in Listing A, you should see something like this on your console:
Starting thread...
Thread is running...
Thread is running...
Thread is running...
Interrupting thread...
Thread is running...
Thread is running...
Thread is running...
Stopping application...
Even after Thread.interrupt() is called, the thread continues to run for a while.
Really interrupting a thread
The best, recommended way to interrupt a thread is to use a shared
variable to signal that it must stop what it is doing. The thread must
check the variable periodically, especially during lengthy operations,
and terminate its task in an orderly manner. Listing B demonstrates this technique.
Running the code in Listing B will generate output like this (notice how the thread exits in an orderly fashion):
Starting thread...
Thread is running...
Thread is running...
Thread is running...
Asking thread to stop...
Thread exiting under request...
Stopping application...
Although this method requires some coding, it is not difficult to
implement and give the thread the opportunity to do any cleanup needed,
which is an absolute requirement for any multithreaded application. Just
be sure to declare the shared variable as volatile or enclose any access to it into synchronized blocks/methods.
So far, so good! But what happens if the thread is blocked waiting for
some event? Of course, if the thread is blocked, it can't check the
shared variable and can't stop. There are plenty of situations when that
may occur, such as calling Object.wait(), ServerSocket.accept(), and DatagramSocket.receive(), to name a few.
They all can block the thread forever. Even if a timeout is employed, it
may not be feasible or desirable to wait until the timeout expires, so a
mechanism to prematurely exit the blocked state must be used.
Unfortunately there is no such mechanism that works for all cases, but
the particular technique to use depends on each situation. In the
following sections, I'll give solutions for the most common cases.
Interrupting a thread with Thread.interrupt()
As demonstrated in Listing A, the method Thread.interrupt()
does not interrupt a running thread. What the method actually does is
to throw an interrupt if the thread is blocked, so that it exits the
blocked state. More precisely, if the thread is blocked at one of the
methods Object.wait, Thread.join, or Thread.sleep, it receives an InterruptedException, thus terminating the blocking method prematurely.
So, if a thread blocks in one of the aforementioned methods, the correct
way to stop it is to set the shared variable and then call the interrupt() method on it (notice that it is important to set the variable first). If the thread is not blocked, calling interrupt()
will not hurt; otherwise, the thread will get an exception (the thread
must be prepared to handle this condition) and escape the blocked state.
In either case, eventually the thread will test the shared variable and
stop. Listing C is a simple example that demonstrates this technique.
As soon as Thread.interrupt() is called in Listing C,
the thread gets an exception so that it escapes the blocked state and
determines that it should stop. Running this code produces output like
this:
Starting thread...
Thread running...
Thread running...
Thread running...
Asking thread to stop...
Thread interrupted...
Thread exiting under request...
Stopping application...
Interrupting an I/O operation
But what happens if the thread is blocked on an I/O operation? I/O can
block a thread for a considerable amount of time, particularly if
network communication is involved. For example, a server may be waiting
for a request, or a network application may be waiting for an answer
from a remote host.
If you're using channels, available with the new I/O API introduced in Java 1.4, the blocked thread will get a ClosedByInterruptException exception. If that is the case, the logic is the same as that used in the third example—only the exception is different.
But you might be using the traditional I/O available since Java 1.0,
since the new I/O is so recent and requires more work. In this case, Thread.interrupt() doesn't help, since the thread will not exit the blocked state. Listing D demonstrates that behavior. Although the interrupt() method is called, the thread does not exit the blocked state.
Fortunately, the Java Platform provides a solution for that case by calling the close()
method of the socket the thread is blocked in. In this case, if the
thread is blocked in an I/O operation, the thread will get a SocketException exception, much like the interrupt() method causes an InterruptedException to be thrown.
The only caveat is that a reference to the socket must be available so that its close() method can be called. That means the socket object must also be shared. Listing E demonstrates this case. The logic is the same as in the examples presented so far.
And here's the sample output you can expect from running Listing E:
Starting thread...
Waiting for connection...
Asking thread to stop...
accept() failed or interrupted...
Thread exiting under request...
Stopping application...
Multithreading is a powerful tool, but it presents its own set of
challenges. One of these is how to interrupt a running thread. If
properly implemented, these techniques make interrupting a thread no
more difficult than using the built-in operations already provided by
the Java Platform.
相关文章
- Java final关键字
- Java 线程安全 Thread-Safety
- java多线程之线程池
- Effective Java 第三版—— 85. 其他替代方式优于Java本身序列化
- 疯狂java讲义 第三版 笔记
- java 线程池底层原理详解与源码分析(补充部分---ScheduledThreadPoolExecutor类分析)
- Java中使用Hutool的ExecutorBuilder实现自定义线程池
- Java 线程池 ThreadPoolExecutor
- 《深入理解Java虚拟机》-----第13章 线程安全与锁优化
- Java对象实例化过程
- Java对象内存分配
- Java Thread 线程
- 进程&线程(&java.lang.Thread)详解
- Java 环境下使用 AES 加密的特殊问题处理
- Java并发之线程间协作Object的wait()、notify()、notifyAll()
- Java 基础(同步方法解决线程安全问题)
- Java 数组排序
- 局域网实时聊天系统(JAVA)--利用Sock
- java线程状态
- 【 java 集合】Set 接口及常用实现类总结
- 【 java 面向对象】内部类
- Java EasyExcel指定列的下标或列名读取Excel数据方法及示例代码
- 报告显示:组件是Java应用易受黑客攻击的关键
- 编程语言之争,谁将会杀死Java?
- Java线程池工作原理
- Java线程等待唤醒机制(加深理解)
- java 线程 Thread 使用介绍,包含wait(),notifyAll() 等函数使用介绍
- 50道Java线程面试题分析及答案
- java 线程池的原理