public class Demo1 {
private static boolean isQuit=false;
public static void main(String[] args) {
//boolean isQuit=false;
Thread thread=new Thread(()->{
while (!isQuit){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread.start();
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("标注位修改,进程退出");
isQuit=true;
}
}
以上是一段通过程序员设置标志位终止多线程的示范代码
isQuit作为类的成员属性和main方法的成员变量是截然不同的,当isQuit作为main方法的成员变量时会出现编译错误,这是为什么呢?
出现错误的原因
lambda表达式拥有“变量捕获”这样的机制,lambda表达式并不是直接访问外部的变量,而是把外部的变量给复制了一份到lambda里面,但是变量捕获有一个限制,被捕获的变量必须是常量,或者被final修饰的变量,所以该变量的值不能被修改,所以就不能成为标志位
为什么要设定变量捕获呢
因为lambda表达式的执行时机是很靠后的,所以在真正执行lambda表达式的时候,局部变量isQuit就可能已经被销毁了,在lambda表达式中去访问一个已经销毁的局部变量是不现实的,所以lambda引人了变量捕获这个机制,将需要调用的外部变量复制一份到lambda中,调用的实践上是lambda复制过来的变量
为什么要对变量捕获进行限制
因为java是通过复制的方式来实现“变量捕获”,要是外面的代码要对这个变量进行修改 就会导致外面的变量变了,lambda表达式里面的变量没变,这样代码很容易出现歧义,所以就直接让外面的变量不能被改变是最省心的。