Do not use thread directly There are two reasons for stop ()
- The execution of the stop() method requires obtaining the lock of the current thread.
- Once the stop() method is executed, all the locks on the current thread will be released immediately, and the thread will stop immediately, which may lead to data security problems.
The execution of the stop() method requires obtaining the lock of the current thread
Thread. The source code of stop () is as follows. You can see that the native method stop0() will eventually be called.
@Deprecated public final void stop() { SecurityManager security = System.getSecurityManager(); if (security != null) { checkAccess(); if (this != Thread.currentThread()) { security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION); } } // A zero status value corresponds to "NEW", it can't change to // not-NEW because we hold the lock. if (threadStatus != 0) { resume(); // Wake up thread if it was suspended; no-op otherwise } // The VM can handle all thread states stop0(new ThreadDeath()); } private native void stop0(Object o);
At this time, we can't see anything. Let's run an example. In this example, we let the thread that counts and outputs run for 100ms and call its stop method,
As expected, the counting process will stop immediately, and then print an exception. However, the result is that each counting process will be completed, and then the exception will be printed.
public class stopTest { public static void main(String[] args) { try { Thread t = new Thread() { public synchronized void run() { try { long start=System.currentTimeMillis(); for (int i = 0; i < 100000; i++) System.out.println("runing.." + i); System.out.println((System.currentTimeMillis()-start)/1000); } catch (Throwable ex) { System.out.println("Caught in run: " + ex); ex.printStackTrace(); } } }; t.start(); // Give t time to get going... Thread.sleep(100); t.stop(); // EXPECT COMPILER WARNING } catch (Throwable t) { System.out.println("Caught in main: " + t); t.printStackTrace(); } } }
// The output result is runing..99994 runing..99995 runing..99996 runing..99997 runing..99998 runing..99999 runing..100000
The reason for the above problems is that the run method of Thread uses synchronized locking, while Thread stop0() also needs to acquire locks to execute. The run method has acquired the lock when it runs, so stop0() is blocked until the lock is released at the end of counting.
Knowing the problem, we modify the lock and use an object as the lock of the thread. final Object lock = new Object(); Use the following code to test
public static void main(String[] args) { final Object lock = new Object(); try { Thread t0 = new Thread() { public void run() { try { synchronized (lock) { System.out.println("thread->" + getName() + " acquire lock."); sleep(3000);// sleep for 3s System.out.println("thread->" + getName() + " release lock."); } } catch (Throwable ex) { System.out.println("Caught in run: " + ex); ex.printStackTrace(); } } }; Thread t1 = new Thread() { public void run() { synchronized (lock) { System.out.println("thread->" + getName() + " acquire lock."); } } }; t0.start(); // Give t time to get going... Thread.sleep(100); //t0.stop(); t1.start(); } catch (Throwable t) { System.out.println("Caught in main: " + t); t.printStackTrace(); } }
If you do not call t0 The stop () method, t0 and T1, can operate normally and obtain locks respectively. The output is:
thread->Thread-0 acquire lock. thread->Thread-0 release lock. thread->Thread-1 acquire lock.
If you call t0 Stop () method, the output result is
thread->Thread-0 acquire lock. thread->Thread-1 acquire lock. Caught in run: java.lang.ThreadDeath java.lang.ThreadDeath at java.lang.Thread.stop(Thread.java:715) at com.yezi.test.timeout.ThreadStopTest.main(ThreadStopTest.java:40)
You can see that t0 directly aborts the operation, throws an exception, and releases the lock. This kind of code that can stop running anywhere is unacceptable because the state of the object it returns is unpredictable.
for instance:
For example, the object obj stores a range of values: the minimum value is low, the maximum value is high, and the low value must not be greater than high. This relationship is protected by lock to avoid the relationship failure caused by race conditions during concurrency. Assuming that the current low value is 5 and the high value is 10, when the thread t obtains the lock, it updates the low value to 15 and is stopped. It's really bad. If the Error caused by stop is not captured, the low value is 15 and the high value is 10, which makes the less than relationship between them not guaranteed, that is, the object state is destroyed! If you catch the Error caused by stop when assigning a value to low, you may continue the assignment of the following high variables, but no one knows in which statement the Error will be thrown. If the relationship between object states is more complex? This way is almost impossible to maintain. It's too complicated! If it is an interrupt operation, it is determined not to throw an Error when executing the low assignment, so that the program is controllable for the consistency of object state.
Original address: https://blog.csdn.net/kingzma/article/details/45739963