Java 解决多线程死循环问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41723615/article/details/88706791

关键字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关键字了,它主要的作用就是当线程访问变量时,强制性从公共堆栈中进行取值。

猜你喜欢

转载自blog.csdn.net/qq_41723615/article/details/88706791
今日推荐