Java多线程:如何不使用static关键字将HashMap传递给Runnable实现类
问题根源
你原来的代码存在两个核心错误:
- 每个
threader实例内部都单独创建了新的ThreadDemo对象,如果去掉map的static修饰,每个ThreadDemo实例会持有独立的map对象,线程之间操作的不是同一个集合,自然统计不到正确结果 - main方法最后打印时又创建了全新的
ThreadDemo实例,这个实例的map从来没有被任何线程操作过,肯定拿不到统计数据
修改方案
通过构造方法将共用的ThreadDemo实例传入Runnable实现类即可,全程不需要使用static修饰map,修改后的完整代码如下:
ThreadDemo.java
import java.util.ArrayList; import java.util.HashMap; public class ThreadDemo { // 移除static修饰,改为普通实例变量 HashMap<String, Integer> map = new HashMap<>(); public String Hi() { return "hi"; } public String Hello() { return "Hello"; } public void addToMap(String item) { if (map.containsKey(item)) { map.put(item, map.get(item) + 1); } else { map.put(item, 1); } } public static void main(String[] args) throws InterruptedException { ArrayList<Thread> all = new ArrayList<>(); // 提前创建全局唯一的ThreadDemo实例,所有线程共用该实例的map ThreadDemo sharedDemo = new ThreadDemo(); for (int i = 0; i < 50; ++i) { // 将共用实例传入threader的构造方法 threader task = new threader(sharedDemo); all.add(new Thread(task)); } for (Thread thread : all) { thread.start(); } for (Thread thread : all) { thread.join(); } // 直接打印共用实例的map即可拿到统计结果 System.out.println(sharedDemo.map); } }
threader.java
public class threader implements Runnable { private final ThreadDemo demo; // 新增构造方法接收外部传入的ThreadDemo实例 public threader(ThreadDemo demo) { this.demo = demo; } @Override public void run() { synchronized(demo.map) { demo.addToMap(demo.Hi()); demo.addToMap(demo.Hello()); } } }
运行结果
修改后所有线程操作的是同一个map对象,最终输出结果为{hi=50, Hello=50},符合预期。
内容的提问来源于stack exchange,提问作者forkbun882
相关产品推荐
相关产品推荐

