Java 解决多线程死循环问题

本文探讨了Java中多线程死循环的问题,分析了同步死循环的示例,并提出使用volatile关键字来解决这个问题。解释了在-JVM-server模式下可能导致死循环的原因,即线程私有堆栈和公共堆栈中变量值不同步。通过加入volatile关键字,确保了线程对变量的访问始终获取最新的公共堆栈值,从而避免死循环。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关键字volatile与死循环

首先来看看一个死循环的案例:

public class printString01 {

private boolean isContinuePrint = true;
	
	
	public boolean isContinuePrint() {
		return isContinuePrint;
	}
	
	public void setContinuePrint(boolean isContinuePrint) {
		this.isContinuePrint = isContinuePrint;
	}
	
	public void printStringMethod(){
		try{
			while(isContinuePrint == true){
				System.out.println("run printStringMethod threadName="
						+ Thread.currentThread().getName());
				Thread.sleep(1000);
			}
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		printString01 printStringService = new printString01();
		printStringService.printStringMethod();
		System.out.println("我要停止它!stopThread=" + Thread.currentThread().getName());
		printStringService.setContinuePrint(false);
	}

}

运行效果:
在这里插入图片描述
造成死循环的原因就是main线程一直在处理while循环,导致不能执行后面的代码。

解决方法一:(解决同步死循环)

public class PrintString0 implements Runnable {

	private boolean isContinuePrint = true;
	
	
	public boolean isContinuePrint() {
		return isContinuePrint;
	}
	
	public void setContinuePrint(boolean isContinuePrint) {
		this.isContinuePrint = isContinuePrint;
	}
	
	public void printStringMethod(){
		try{
			while(isContinuePrint == true){
				System.out.println("run printStringMethod threadName="
						+ Thread.currentThread().getName());
				Thread.sleep(1000);
			}
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void run() {
		printStringMethod();
	}
	
	public static void main(String[] args) {
		PrintString0 printStringService = new PrintString0();
		new Thread(printStringService).start();
		System.out.println("我要停止它!stopThread=" + Thread.currentThread().getName());
		printStringService.setContinuePrint(false);
	}

}

运行效果:
在这里插入图片描述
上面使用实现Runnable接口解决同步死循环。
但是运行在-server服务器模式中64bit的JVM上时,会出现死循环。
解决的办法就是使用volatile关键字。

解决异步死循环:

public class RunThread extends Thread {

	private boolean isRunning = true;
	
	public boolean isRunning() {
		return isRunning;
	}

	public void setRunning(boolean isRunning) {
		this.isRunning = isRunning;
	}
	
	@Override
	public void run() {
		System.out.println("进入run了");
		while (isRunning == true) {
		}
		System.out.println("线程被停止了!");
	}
	
	public static void main(String[] args) {
		try {
			RunThread thread = new RunThread();
			thread.start();
			Thread.sleep(1000);
			thread.setRunning(false);
			System.out.println("已经赋值为false");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

运行效果:
在这里插入图片描述
是什么样的原因造成将JVM设置为-server时就出现死循环呢?
在启动RunThread.java线程时,变量private boolean isRunning = true;存在于公共堆栈及线程的私有堆栈中,在JVM被设置为-server模式时为了线程运行的效率,线程一直在私有堆栈中取得isRunning的值是true。而代码thread.setRunning(false);虽然被执行,更新的却是公共堆栈中的isRunning变量值为false,所以一直就是死循环状态。
内存结构图:线程的私有堆栈
在这里插入图片描述

加入volatile关键字:

public class RunThread extends Thread {

	volatile private boolean isRunning = true;
	
	public boolean isRunning() {
		return isRunning;
	}

	public void setRunning(boolean isRunning) {
		this.isRunning = isRunning;
	}
	
	@Override
	public void run() {
		System.out.println("进入run了");
		while (isRunning == true) {
		}
		System.out.println("线程被停止了!");
	}
	
	public static void main(String[] args) {
		try {
			RunThread thread = new RunThread();
			thread.start();
			Thread.sleep(1000);
			thread.setRunning(false);
			System.out.println("已经赋值为false");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

运行效果:

在这里插入图片描述
死循环有可能时私有堆栈中的值和公共堆栈中的值不同步造成的。
解决这样的情况要使用volatile关键字了,它主要的作用就是当线程访问变量时,强制性从公共堆栈中进行取值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值