springboot中使用timer,即多线程,给变量赋值的几个注意点

最近在springboot中需要用到定时器,永不停歇那种,timer,其实就是新增加一条线程,然后我还想往线程里传入变量,然后我还想在线程里改变变量的值。这个是很危险的动作,琢磨了一下这个java的多线程,做一下记录。

一、错误示范

1、当你在函数中定义一个变量,想要在后面生成的定时器中传入值。如果你像这样传入:

	@RequestMapping(value = "/test")
	@ResponseBody
	public void test(HttpServletRequest request,HttpSession session){
    
    
		String test="";
		Timer timer=new Timer();
		timer.schedule(new TimerTask() {
    
    
            	public void run() {
    
    
            		test="another value";
            	}
	}

这是一定会报这样的错的:

Local variable test defined in an enclosing scope must be final or effectively final

原因很简单,就是告诉你只有传入线程的值只能是final属性。
2、然后,你就开始改啊改:

	@RequestMapping(value = "/test")
	@ResponseBody
	public void test(HttpServletRequest request,HttpSession session){
    
    
		final String test="";
		Timer timer=new Timer();
		timer.schedule(new TimerTask() {
    
    
            	public void run() {
    
    
            		test="another value";
            	}
	}

然后,又会出现新的错误:

The final local variable test cannot be assigned, since it is defined in an enclosing type

这句话的意思就是告诉你,因为你定义的值是final,所以是不能被赋值的。现在你心里是不是一万只草泥马奔腾而过。
所以,常规手段是没用的。

二、正解

1、把变量定义在全局上。

	String test="";
	@RequestMapping(value = "/test")
	@ResponseBody
	public void test(HttpServletRequest request,HttpSession session){
    
    
		Timer timer=new Timer();
		timer.schedule(new TimerTask() {
    
    
            	public void run() {
    
    
            		test="another value";
            	}
	}

这个方法可以解决一部分问题,但是不能解决所有问题,就是当多个前端都调用这个test()函数映射时,这就混乱了,变量一会被这个前端改成了这个值,一会又被另一个前端改成了那个值。这个方法只能用在修改一个全局参数的情况下,这个参数是所有前端都需要修改的那种。
2、定义数组传入。
有人问为什么数组传入了线程还能改变,这不是bug吗?不是的,数组其实也有不能改变的属性,这个属性我看到有一个网友解释说是,数组的长度。数组的长度是不能改变的。
不过这就方便了我们在函数中定义一个数组传入线程。

	@RequestMapping(value = "/test")
	@ResponseBody
	public void test(HttpServletRequest request,HttpSession session){
    
    
		String[] test=new String[1];
		Timer timer=new Timer();
		timer.schedule(new TimerTask() {
    
    
            	public void run() {
    
    
            		test[0]="another value";
            	}
	}

三、其他需要注意的点

1、不要被那些报错以及网上的只言片语给误导了,往另一个线程传值不需要把变量的属性定义为final,那些报错只是想告诉你,在线程中有些属性不能改变,而不是说要你给变量属性加上final,传值到线程内,跟不是线程内没有任何区别,不一样的,只是赋值,在线程内给线程外的变量赋值需要费一番波折。
2、如果你是从前台传过来的值,又刚好跟我一样习惯用request.getParameter(“xxx”)来取值,那你一定要注意,不要把取值这句话写到了线程里面去,你可以写在线程外面,或者直接用注释取值:
错误示范:

	@RequestMapping(value = "/test")
	@ResponseBody
	public void test(HttpServletRequest request,HttpSession session){
    
    
		String[] test=new String[1];
		Timer timer=new Timer();
		timer.schedule(new TimerTask() {
    
    
            	public void run() {
    
    
            		String mvalue=request.getParameter("value");//在这
            		test[0]="another value";
            	}
	}

正确示范:

	@RequestMapping(value = "/test")
	@ResponseBody
	public void test(HttpServletRequest request,HttpSession session){
    
    
		String mvalue=request.getParameter("value");//在这
		String[] test=new String[1];
		Timer timer=new Timer();
		timer.schedule(new TimerTask() {
    
    
            	public void run() {
    
    
            		test[0]="another value";
            	}
	}

猜你喜欢

转载自blog.csdn.net/baidu_31788709/article/details/104582064