java多线程:使用标志自然终止线程,但是在终止后还是执行了线程

林瑎 2020-02-15 12:20:27
问题如标题。我使用标志来自然终止线程,但是在改变标志后,理论上终止了线程,但是还是打印出了线程的执行代码。具体代码如下:

public class TerminateThread implements Runnable{
//加入标识,标记程序是否执行
private boolean flag = true;
private String name;

public TerminateThread(String name) {
this.name = name;
}

@Override
public void run() {
int i=0;
//利用标识标记线程是否执行
while (flag) {
System.out.println(name + " 正在场上打球 "+i++);
}
}

//改变标识,线程执行结束
public void terminate(){
this.flag=false;
}

public static void main(String[] args){
//新建比赛进程
TerminateThread terminateThread =new TerminateThread("Kobe");
new Thread(terminateThread).start();

//main线程相当于整场比赛,i为比赛时间
for (int i=0;i<100;i++){
//当比赛进行到第80min,科比下场休息
if (i==80){
terminateThread.terminate();//线程终止
System.out.println("Kobe 下场休息");
}

System.out.println("比赛进行到第 "+i+" 分钟");
}
}
}


执行结果如下图:

这次的执行发生错误。

这次的执行没有问题。
基本上代码的执行结果只有两种类型,在线程终止前,线程已经执行过;或者在线程终止前,从未执行。而发生错误的就是从未执行过的情况。




...全文
285 9 打赏 收藏 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
林瑎 2020-02-16
  • 打赏
  • 举报
回复
我的理解是线程进入while循环时可能参数还没有改变,但是在打印时可能发生改变,所以需要做同步处理,并且判断标志。这样可以吗?
林瑎 2020-02-16
  • 打赏
  • 举报
回复
我采用了7楼的答案,代码主要的问题是涉及到flag的修改,以及两个线程System.out.println()输出。所以要对这两个做同步处理,我写了两个方法,把他们扔进去,加上synthronized关键字就好。
修改后的代码如下

public class TerminateThread implements Runnable {
//加入标识,标记程序是否执行
private boolean flag = true;
private String name;

public TerminateThread(String name) {
this.name = name;
}

public static void main(String[] args) {
//新建比赛进程
TerminateThread terminateThread = new TerminateThread("Kobe");
new Thread(terminateThread).start();

//main线程相当于整场比赛,i为比赛时间
for (int i = 0; i < 30; i++) {
//当比赛进行到第80min,科比下场休息
if (i == 15) {
//???在终止线程时,如果线程处于就绪状态会怎么样???
terminateThread.terminate();//线程终止
System.out.println("Kobe 下场休息");
}

System.out.println("比赛进行到第 " + i + " 分钟");
}
}

@Override
public void run() {
int i = 0;

//利用标识标记线程是否执行
while (flag) {
printInfo(i++);
}
}

public synchronized void printInfo(int i) {
if (flag){
System.out.println(name + " 正在场上打球 当前flag为 " + flag + " ,这是第 " + i);
}
}

//改变标识,线程执行结束
public synchronized void terminate() {
this.flag = false;
}
}

林瑎 2020-02-15
  • 打赏
  • 举报
回复
引用 1 楼 再启动 的回复:
flag被多线程修改,两个线程里对象的值可能不一样,要增加锁 public void terminate(){ Object lock = new Object(); synchronized (lock) { this.flag = false; } }
多线程吗?我的主线程只修改了一次flag啊
爱吃鱼的ねこ 2020-02-15
  • 打赏
  • 举报
回复
把flag用volatile 修饰
再启动 2020-02-15
  • 打赏
  • 举报
回复
用锁或volatile都是OK的 你这个问题可以看到,每次出问题的时候:打印“Kobe 下场休息” 只会再打一次“Kobe 正在场上打球” 如果你把这行注掉:System.out.println("比赛进行到第 "+i+" 分钟"); ,就只会打印 “Kobe 下场休息” main方法本身是一个线程,new Thread(terminateThread).start();语句又开了一个线程。两个线程都需要调用输出流,所以问题就出在线程的中断上。 问题不是必现的,如果子线程正好要打印的时候被挂起,这个时候主线程打印后,子线程再执行就出问题了。 把代码修改成这样就不会出现问题,修改和打印的时候都使用对象锁,并且打印时在锁内部检查flag, 说明这个推断应该是对的: @Override public void run() { int i=0; //利用标识标记线程是否执行 while (flag) { print(i++); // System.out.println(name + " 正在场上打球 "+ i++); } } public synchronized void print(int i) { if (flag) { System.out.println(name + " 正在场上打球 " + i); } } //改变标识,线程执行结束 public synchronized void terminate(){ this.flag = false; }
ma241677131 2020-02-15
  • 打赏
  • 举报
回复
进来学习一下
再启动 2020-02-15
  • 打赏
  • 举报
回复
flag被多线程修改,两个线程里对象的值可能不一样,要增加锁 public void terminate(){ Object lock = new Object(); synchronized (lock) { this.flag = false; } }
三仙半 2020-02-15
  • 打赏
  • 举报
回复
循环跑得太快了,说不准哪个线程先执行,你把主线程的for循环也放到一个子线程里面,然后,循环体里面做上线程休眠,同样,比赛线程的循环里面也做上线程休眠,然后再看效果。
林瑎 2020-02-15
  • 打赏
  • 举报
回复
2楼和三楼两位的回复我都试了,运行结果还是不变。
我有一点想法,就是start线程后,进入就绪状态,我自然终止线程,那么线程是直接被杀死了吗?

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧