(随笔)龟兔赛跑(多线程调用同一资源时一个线程结束时其他线程保持运行)

问题:当其一线程结束运行后其他线程保持运行而非结束

现象:控制台会输出两次the winner is:xxx

代码如下

package com.demo01;

/**
 * TODO 模拟归途赛跑
 *
 * @author pangyangjian
 * @since 2023/8/16 16:10
 */
public class TextThread_5 implements Runnable {
	
	@Override
	public void run() {
		for (int i = 0; i <= 200; i++) {
			System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");
			if(!gameOver(i)){
				break;
			}
		}
	}
	
	public boolean gameOver(int step) {
		if (step == 200) {
			System.out.println("the winner is:" + Thread.currentThread().getName());
			return false;
		}
		return true;
	}
	
	public static void main(String[] args) {
		TextThread_5 race = new TextThread_5();
		new Thread(race, "Rabbit").start();
		new Thread(race, "Turtle").start();
	}
}

回答:当一个线程结束后,另一个线程并不会立即结束的原因是,gameOver()方法返回true时,循环会继续执行。即使一个线程已经达到了step == 200的条件,另一个线程仍然可以继续打印输出。
解决方法:通过共享的标志变量来控制两个线程的结束。可以将标志变量放在TextThread_5类的成员变量中。

改进后代码如下

package com.demo01;

/**
 * TODO 模拟归途赛跑
 *
 * @author pangyangjian
 * @since 2023/8/16 16:10
 */
public class TextThread_5 implements Runnable {
	private volatile boolean gameOver = false;
	
	@Override
	public void run() {
		for (int i = 0; i <= 200; i++) {
			System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");
			if (!gameOver(i)) {
				break;
			}
			if ("Rabbit".equals(Thread.currentThread().getName()) && i % 100 == 0) {
				try {
					Thread.sleep(1);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public synchronized boolean gameOver(int step) {
		if (gameOver) {
			return false;
		}
		if (step >= 200) {
			System.out.println("the winner is:" + Thread.currentThread().getName());
			gameOver = true;
			return false;
		}
		return true;
	}
	
	public static void main(String[] args) {
		TextThread_5 race = new TextThread_5();
		new Thread(race, "Rabbit").start();
		new Thread(race, "Turtle").start();
	}
}

posted @ 2023-08-16 18:41  Joseph·Jonardo  阅读(11)  评论(0)    收藏  举报