Thread.stop()方法,不推荐使用,太过暴力,会强行把执行到一半的线程终止,可能会引起一些数据不一致的问题。
stop()方法在结束线程时,会直接终止线程,并且会立即释放这个线程所持有的锁。而这些锁恰恰是用来维持对象一致性的。
/**
* 启动两个线程模拟数据不一致的问题
* ChangeThread:对对象user的属性写入相同的值
* ReadThread:当读到user对象中的id与name不一致时,打印这个对象
*
* @author MatrixOne001
*
*/
public class StopThreadUnsafe {
public static User user = new User();
public static class User{
private long id = 0 ;
private String name = "0" ;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
public static class ChangeThread extends Thread{
@Override
public void run() {
while(true){
synchronized(user){
long v = System.currentTimeMillis() ;
user.setId(v);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
user.setName(String.valueOf(v));
}
Thread.yield();
}
}
}
public static class ReadThread extends Thread{
@Override
public void run() {
while(true){
synchronized(user){
// 获取对象user中id与name值不相同的情况,即一致性错误的对象
if( user.getId() != Long.valueOf( user.getName() )){
System.out.println( user );
}
}
Thread.yield();
}
}
}
public static void main(String[] args) throws InterruptedException {
new ReadThread().start();
while(true){
Thread t = new ChangeThread();
t.start();
t.sleep(150);
t.stop(); //已被标记为废弃的方法
}
}
}
截取部分运行结果
User [id=1495379861337, name=1495379861227]
User [id=1495379861493, name=1495379861384]
如何合理的关闭线程
方法其实很简单,只是需要由我们自行决定线程何时退出就可以了。
修改上面 ChangeThread 中的代码,增加一个标记变量stopme,用来控制线程的关闭
public static class ChangeThread extends Thread{
volatile boolean stopme = false;
public void stopMe(){
stopme = true;
}
@Override
public void run() {
while(true){
synchronized(user){
//增加一个判断,如果变量stopme被设置为true,线程退出
if( stopme ){
System.out.println( "exit by stop me ");
break;
}
long v = System.currentTimeMillis() ;
user.setId(v);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
user.setName(String.valueOf(v));
}
Thread.yield();
}
}
}
同时修改主方法
new ReadThread().start();
while(true){
ChangeThread t = new ChangeThread();
t.start();
t.sleep(150);
// t.stop(); //已被标记为废弃的方法
t.stopMe(); //使用自定义的方法来取代stop()
}