版权声明:本文为博主原创文章,未经博主允许不得转载。 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关键字了,它主要的作用就是当线程访问变量时,强制性从公共堆栈中进行取值。