zoukankan      html  css  js  c++  java
  • 循环中多线程参数为空bug

    循环中多线程参数为空bug

    问题来由

    在循环中使用多线程执行是常见的做法,使用map作为多线程内部的函数传入参数,然而在多线程后使用clear清空map中的内容,就会发现多线程中的数据没了。如下所示:

    package com.example.redis_test.thread;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    import java.util.concurrent.ThreadPoolExecutor;
    
    
    public class ThreadConfig {
        //使用@Bean返回一个spring接管的bean对象。
      	@Bean
        ThreadPoolTaskExecutor defaultThreadPoolExecutor() {
            ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
            threadPoolTaskExecutor.setCorePoolSize(0);
            threadPoolTaskExecutor.setCorePoolSize(10);
            threadPoolTaskExecutor.setQueueCapacity(20);
            threadPoolTaskExecutor.setRejectedExecutionHandler(new 				ThreadPoolExecutor.CallerRunsPolicy());
            threadPoolTaskExecutor.initialize();
            return threadPoolTaskExecutor;
        }
    }
    

    测试一:

    package com.example.redis_test;
    
    import com.example.redis_test.thread.ThreadConfig;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    import java.util.HashMap;
    import java.util.Map;
    
    @SpringBootTest
    class RedisTestApplicationTests {
    
        @Autowired
        ThreadPoolTaskExecutor threadPoolTaskExecutor;
        @Test
        void contextLoads() {
            Map<String,String> map = new HashMap<>();
            for(int i = 0; i < 5; i++){
                map.put(String.valueOf(i),String.valueOf(i));
                String k = String.valueOf(i);
                threadPoolTaskExecutor.execute(()->{
                    System.out.println(map.get(String.valueOf(k)));
                });
                map.clear();
            }
        }
    
    }
    
    /**
     * 输出结果:null, null, null, null, null
     * 
     */
    

    测试二:

    package com.example.redis_test;
    
    import com.example.redis_test.thread.ThreadConfig;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    import java.util.HashMap;
    import java.util.Map;
    
    @SpringBootTest
    class RedisTestApplicationTests {
    
        @Autowired
        ThreadPoolTaskExecutor threadPoolTaskExecutor;
        @Test
        void contextLoads() {
    
            for(int i = 0; i < 5; i++){
                Map<String,String> map = new HashMap<>();
                map.put(String.valueOf(i),String.valueOf(i));
                String k = String.valueOf(i);
                threadPoolTaskExecutor.execute(()->{
                    System.out.println(map.get(String.valueOf(k)));
                });
            }
        }
    
    }
    /**
     * 输出结果:0, 1, 2, 3, 4
     *
     */
    

    分析

    首先这是因为内存模型的不熟练。

    下图是上述场景的内存图

    主线程和线程1都会引用map对象。所以我们看代码

    threadPoolTaskExecutor.execute(()->{
                    System.out.println(map.get(String.valueOf(k)));
                });
                map.clear();
    

    这一段里如果main运行的速度比线程的速度快,那么就会将map对象清空。

    解决办法

    1. 在for循环里使用Map<String,String> map = new HashMap<>();(按照测试2)
    2. Map<String,String> keyMap = new HashMap<>(map); 然后在多线程使用keyMap,主线程使用map。
  • 相关阅读:
    HDU-3790 最短路径问题(双重权值)
    Graph (floyd)
    POJ-3259 Wormholes(判断负环、模板)
    HDU-1317 XYZZY
    HDU-1548 A strange lift(单源最短路 或 BFS)
    最小生成树(模板 prim)
    【面试】386- JavaScript 面试 20 个核心考点
    【Koa】385- koa框架的快速入门与使用
    【小程序】384- 如何一人五天开发完复杂小程序(前端必看)
    【React】383- React Fiber:深入理解 React reconciliation 算法
  • 原文地址:https://www.cnblogs.com/clnsx/p/12894765.html
Copyright © 2011-2022 走看看