`
samsongbest
  • 浏览: 167723 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Thread stop不能用了

    博客分类:
  • Java
 
阅读更多

http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

http://www.cnblogs.com/gpcuster/archive/2010/01/18/1650273.html

Java Thread Primitive Deprecation

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.


Couldn't I just catch the ThreadDeath exception and fix the damaged object?

In theory, perhaps, but it would vastly complicate the task of writing correct multithreaded code. The task would be nearly insurmountable for two reasons:

  1. A thread can throw a ThreadDeath exception almost anywhere . All synchronized methods and blocks would have to be studied in great detail, with this in mind.
  2. A thread can throw a second ThreadDeath exception while cleaning up from the first (in the catch or finally clause). Cleanup would have to repeated till it succeeded. The code to ensure this would be quite complex.

In sum, it just isn't practical.


What about Thread.stop(Throwable) ?

In addition to all of the problems noted above, this method may be used to generate exceptions that its target thread is unprepared to handle (including checked exceptions that the thread could not possibly throw, were it not for this method). For example, the following method is behaviorally identical to Java's throw operation, but circumvents the compiler's attempts to guarantee that the calling method has declared all of the checked exceptions that it may throw:

    static void sneakyThrow(Throwable t) {
        Thread.currentThread().stop(t);
    }

What should I use instead of Thread.stop ?

Most uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. To ensure prompt communication of the stop-request, the variable must be volatile (or access to the variable must be synchronized).

For example, suppose your applet contains the following start , stop and run methods:

    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();
        }
    }

You can avoid the use of Thread.stop by replacing the applet's stop and run methods with:

    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();
        }
    }

How do I stop a thread that waits for long periods (e.g., for input)?

That's what the Thread.interrupt method is for. The same "state based" signaling mechanism shown above can be used, but the state change (blinker = null , in the previous example) can be followed by a call to Thread.interrupt , to interrupt the wait:

    public void stop() {
        Thread moribund = waiter;
        waiter = null;
        moribund.interrupt();
    }

For this technique to work, it's critical that any method that catches an interrupt exception and is not prepared to deal with it immediately reasserts the exception. We say reasserts rather than rethrows , because it is not always possible to rethrow the exception. If the method that catches the InterruptedException is not declared to throw this (checked) exception, then it should "reinterrupt itself" with the following incantation:

    Thread.currentThread().interrupt();

This ensures that the Thread will reraise the InterruptedException as soon as it is able.


What if a thread doesn't respond to Thread.interrupt ?

In some cases, you can use application specific tricks. For example, if a thread is waiting on a known socket, you can close the socket to cause the thread to return immediately. Unfortunately, there really isn't any technique that works in general. It should be noted that in all situations where a waiting thread doesn't respond to Thread.interrupt , it wouldn't respond to Thread.stop either. Such cases include deliberate denial-of-service attacks, and I/O operations for which thread.stop and thread.interrupt do not work properly.


Why are Thread.suspend and Thread.resume deprecated?

Thread.suspend is inherently deadlock-prone. If the target thread holds a lock on the monitor protecting a critical system resource when it is suspended, no thread can access this resource until the target thread is resumed. If the thread that would resume the target thread attempts to lock this monitor prior to calling resume , deadlock results. Such deadlocks typically manifest themselves as "frozen" processes.


What should I use instead of Thread.suspend and Thread.resume ?

As with Thread.stop , the prudent approach is to have the "target thread" poll a variable indicating the desired state of the thread (active or suspended). When the desired state is suspended, the thread waits using Object.wait . When the thread is resumed, the target thread is notified using Object.notify .

For example, suppose your applet contains the following mousePressed event handler, which toggles the state of a thread called blinker :

    private boolean threadSuspended;

    Public void mousePressed(MouseEvent e) {
        e.consume();

        if (threadSuspended)
            blinker.resume();
        else
            blinker.suspend();  // DEADLOCK-PRONE!

        threadSuspended = !threadSuspended;
    }

You can avoid the use of Thread.suspend and Thread.resume by replacing the event handler above with:

    public synchronized void mousePressed(MouseEvent e) {
        e.consume();

        threadSuspended = !threadSuspended;

        if (!threadSuspended)
            notify();
    }

and adding the following code to the "run loop":

                synchronized(this) {
                    while (threadSuspended)
                        wait();
                }

The wait method throws the InterruptedException , so it must be inside a try ... catch clause. It's fine to put it in the same clause as the sleep . The check should follow (rather than precede) the sleep so the window is immediately repainted when the the thread is "resumed." The resulting run method follows:

    public void run() {
        while (true) {
            try {
                Thread.currentThread().sleep(interval);

                synchronized(this) {
                    while (threadSuspended)
                        wait();
                }
            } catch (InterruptedException e){
            }
            repaint();
        }
    }

Note that the notify in the mousePressed method and the wait in the run method are inside synchronized blocks. This is required by the language, and ensures that wait and notify are properly serialized. In practical terms, this eliminates race conditions that could cause the "suspended" thread to miss a notify and remain suspended indefinitely.

While the cost of synchronization in Java is decreasing as the platform matures, it will never be free. A simple trick can be used to remove the synchronization that we've added to each iteration of the "run loop." The synchronized block that was added is replaced by a slightly more complex piece of code that enters a synchronized block only if the thread has actually been suspended:

                if (threadSuspended) {
                    synchronized(this) {
                        while (threadSuspended)
                            wait();
                    }
                }

In the absence of explicit synchronization, threadSuspended must be made volatile to ensure prompt communication of the suspend-request.

The resulting run method is:

    private boolean volatile threadSuspended;

    public void run() {
        while (true) {
            try {
                Thread.currentThread().sleep(interval);

                if (threadSuspended) {
                    synchronized(this) {
                        while (threadSuspended)
                            wait();
                    }
                }
            } catch (InterruptedException e){
            }
            repaint();
        }
    }

Can I combine the two techniques to produce a thread that may be safely "stopped" or "suspended"?

Yes; it's reasonably straightforward. The one subtlety is that the target thread may already be suspended at the time that another thread tries to stop it. If the stop method merely sets the state variable (blinker ) to null, the target thread will remain suspended (waiting on the monitor), rather than exiting gracefully as it should. If the applet is restarted, multiple threads could end up waiting on the monitor at the same time, resulting in erratic behavior.

To rectify this situation, the stop method must ensure that the target thread resumes immediately if it is suspended. Once the target thread resumes, it must recognize immediately that it has been stopped, and exit gracefully. Here's how the resulting run and stop methods look:

    public void run() {
        Thread thisThread = Thread.currentThread();
        while (blinker == thisThread) {
            try {
                thisThread.sleep(interval);

                synchronized(this) {
                    while (threadSuspended && blinker==thisThread)
                        wait();
                }
            } catch (InterruptedException e){
            }
            repaint();
        }
    }

    public synchronized void stop() {
        blinker = null;
        notify();
    }

If the stop method calls Thread.interrupt , as described above, it needn't call notify as well, but it still must be synchronized. This ensures that the target thread won't miss an interrupt due to a race condition.


What about Thread.destroy ?

Thread.destroy has never been implemented. If it were implemented, it would be deadlock-prone in the manner of Thread.suspend . (In fact, it is roughly equivalent to Thread.suspend without the possibility of a subsequent Thread.resume .) We are not implementing it at this time, but neither are we deprecating it (forestalling its implementation in future). While it would certainly be deadlock prone, it has been argued that there may be circumstances where a program is willing to risk a deadlock rather than exit outright.


Why is Runtime.runFinalizersOnExit deprecated?

Because it is inherently unsafe. It may result in finalizers being called on live objects while other threads are concurrently manipulating those objects, resulting in erratic behavior or deadlock. While this problem could be prevented if the class whose objects are being finalized were coded to "defend against" this call, most programmers do not defend against it. They assume that an object is dead at the time that its finalizer is called.

Further, the call is not "thread-safe" in the sense that it sets a VM-global flag. This forces every class with a finalizer to defend against the finalization of live objects!

分享到:
评论

相关推荐

    为什么不鼓励使用 Thread.stop?

    标题 "为什么不鼓励使用 Thread.stop" 涉及到的是Java多线程编程中的一个重要话题,主要探讨了为何在实际开发中不建议直接使用 `Thread.stop` 方法来终止一个线程的执行。 在Java中,`Thread.stop` 被设计为停止一...

    thread stop tools

    综上所述,"Thread Stop Tools"如IceSword是开发者不可或缺的工具,它们在多线程编程、系统调试、性能分析和安全防护等多个方面发挥着重要作用。理解和熟练使用这些工具,对于提升软件质量、优化系统性能以及保障...

    RT-Thread常见函数.zip_RTT_rt thread_rt-thread函数_rt_thread函数_手册

    这份手册深入浅出地介绍了RTT的核心函数,使得开发者能清晰地掌握RTT的调用关系,提高开发效率。 RTT的核心功能包括任务管理、信号量、互斥锁、消息队列、事件、定时器、内存管理等。手册中可能涵盖了以下主要知识...

    认识Thread和Runnable

    * 当线程调用 wait() 方法后会进入等待队列(进入这个状态会释放所占有的所有资源,与阻塞状态不同),进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用 notify() 或 notifyAll() 方法才能被唤醒。...

    android service thread toast handler

    因为Android的UI线程(主线程)不能执行耗时操作,否则会导致应用无响应(ANR),所以通常会在`Thread`中处理这些任务,以保持用户体验的流畅性。有两种常见的创建线程的方式:继承`Thread`类或实现`Runnable`接口。...

    线程组ThreadGroup

    ThreadGroup 也可以用来实现线程安全的机制,例如使用 ThreadGroup 中的 lock 对象来实现线程同步,使用 ThreadGroup 中的 Condition 对象来实现线程等待和唤醒等。 ThreadGroup 是 Java 中的一种强大的线程管理...

    线程示例WorkerThread_demo

    这个类的实例可能会被`WorkerThread`在`DoWork`方法中使用,确保这些操作不会阻塞UI线程。 `AssemblyInfo.cs`是C#项目的元数据文件,包含关于程序集的信息,如版本、版权和公钥等。 `.csproj`和`.sln`文件是项目和...

    RT-Thread编程指南

    - **线程脱离**:使用`rt_thread_detach()`使一个线程脱离其创建者。 - **线程启动**:调用`rt_thread_start()`使一个线程进入就绪状态。 - **当前线程**:通过`rt_thread_self()`获取当前执行线程的信息。 - **线程...

    STM32L496使用EasyFlash完成KV参数存储【RT-Thread工程,支持STM32L4系列单片机】.zip

    RT-Thread的能源管理功能,配合STM32L496的低功耗模式,可以在不影响性能的情况下,进一步优化系统功耗。例如,当系统空闲时,可以通过进入STOP或STANDBY模式来降低电流消耗。 此外,对于STM32L4系列单片机,RT-...

    java线程中断之interrupt和stop.docx

    使用`stop`方法可能会导致程序出现不稳定的情况。 ##### 3.2 方法签名 ```java public final void stop() ``` ##### 3.3 使用示例 下面是一个简单的示例,展示了如何使用`stop`方法终止线程: ```java public ...

    C++_thread.zip

    1. **线程创建**:使用`std::thread`类可以创建新的线程。创建线程时,需要传递一个函数或者成员函数的引用或指针,以及其参数。例如: ```cpp void thread_function(int arg) { // 线程执行的代码 } int main...

    thread-VC.rar_vc thread

    只需声明一个可调用对象(如函数、成员函数或lambda表达式)并传递给`std::thread`构造函数,就能创建一个新线程执行该可调用对象。 4. **线程同步**:在多线程环境中,数据同步和互斥访问是关键问题。VC提供了多种...

    理解多线程,写一个多线程应用程序,要求能在用户级实现线程的调度,如启动、挂起、恢复、停止,的C thread、java thread实现。

    // thread.stop(); // 停止线程(不推荐,因为不安全) // thread.interrupt(); // 中断线程,通常用于通知线程退出循环 } } ``` 在用户级线程调度中,应用程序负责管理和调度线程的执行。这意味着当一个线程...

    thread-gc-分析.7z

    例如,垃圾收集过程中可能会暂停所有用户线程,这就是所谓的“Stop-the-world”事件。减少这类事件的持续时间对于提升系统响应性至关重要。同时,长时间运行的线程可能产生大量临时对象,增加垃圾收集的负担,因此...

    在MatlabGUI里面启动或者暂停Simulink模型-start_and_stop.mdl

    在start simulation里面,直接用sim函数,这个大家好像都会: % --- Executes on button press in startsim. function startsim_Callback % hObject handle to startsim % eventdata reserved - to be defined ...

    在MatlabGUI里面启动或者暂停Simulink模型-start_and_stop_gui.fig

    在start simulation里面,直接用sim函数,这个大家好像都会: % --- Executes on button press in startsim. function startsim_Callback % hObject handle to startsim % eventdata reserved - to be defined ...

    Java多线程-Thread类的常用结构及线程优先级

    - `setPriority(int priority)`:设置线程的优先级,需要注意不能设置超出范围的优先级。 3. 案例 通常,我们不会频繁地调整线程优先级,因为这可能会导致不公平的执行。但在某些特定场景下,如处理紧急任务,...

    在MatlabGUI里面启动或者暂停Simulink模型-start_and_stop_gui.m

    在start simulation里面,直接用sim函数,这个大家好像都会: % --- Executes on button press in startsim. function startsim_Callback % hObject handle to startsim % eventdata reserved - to be defined ...

    Java终止线程实例和stop()方法源码阅读

    Java终止线程实例和stop()方法源码阅读 Java 中的线程是程序中的执行单元,Java ...Java 中的线程终止可以使用退出标志或 interrupt() 方法来实现,但是一定要避免使用已弃用的 stop() 方法,以免出现线程安全问题。

Global site tag (gtag.js) - Google Analytics