运行以下代码时:

import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;

public final class ThreadTest {
    int N = 4;
    Map<Integer, Proxy> proxy = Collections.synchronizedMap(new TreeMap<>());
    Proxy p;
    
    public static void main(String[] args) {
        new ThreadTest();
    }
    
    public ThreadTest() {
        Thread[] t = new Thread[N];
        for(int c=0;c<N;c++) {
            final int i = c;
            t[i] = new Thread(() -> {
                try {
                    System.out.println( "From thread: " + i );
                    p = new Proxy(i);
                    proxy.put(i, p);
                    p.init();
                } catch (Exception e){}
            });
            t[i].start();
        }
        for(int c=0;c<N;c++) {
            try {
                t[c].join();
            } catch (InterruptedException e){}
        }
    }
    
    public class Proxy {
        int index;
        
        public Proxy(int index) {
            this.index = index;
            System.out.println( "Proxy: " + index );
        }
        
        public void init() {
            System.out.println("Initializing " + index );
        }
    }
}

来自方法init()的打印索引不是唯一的. 以下是输出示例:

From thread: 0
From thread: 1
From thread: 2
From thread: 3
Proxy: 0
Proxy: 3
Proxy: 2
Proxy: 1
Initializing 3
Initializing 3
Initializing 1
Initializing 2

虽然我已经将TreeMapCollections.synchronizedMap()同步,但对于未同步的Map,结果是相同的. 考虑到它只是一个看跌方法,并且索引已经完全改变,这种行为似乎相当奇怪. 有人能解释一下发生了什么事吗? 谢谢.

推荐答案

你的问题是你的p变量被所有线程共享.

init中的打印结果可以看出,在init之前,p变量被另一个线程重写的代码块被调用

                p = new Proxy(i);
                proxy.put(key, p);
                p.init();

Java相关问答推荐

在URL类图中表示Java swing类

OpenJDK、4K显示和文本质量

转换为Biggram

ittext pdf延迟签名,签名无效

使用标记时,场景大纲不在多个线程上运行

当我已经安装了其他版本的Java时,如何在Mac OSX 14.3.1上安装Java 6?

调用引发泛型异常的泛型方法时出现编译错误

Java LocalTime.parse在本地PC上的Spring Boot中工作,但在Docker容器中不工作

生成桥方法以解决具有相同擦除的冲突方法

如何从Keyloak映射Hibernate实体中的用户

在向WebSphere中的文档添加元素时iText挂起

Spring Boot&;Docker:无法执行目标org.springframework.boot:spring-boot-maven-plugin:3.2.0:build-image

Cordova Android Gradle内部版本组件不兼容

将关闭拍卖的TimerService

使用for循环时出现堆栈溢出错误,但如果使用if块执行相同的操作,则不会产生错误

如何通过用户ID向用户发送私信

整数->;双取消框,但双->;int不';t开箱.为什么?

为什么我得到默认方法的值而不是被覆盖的方法的值?

message.acknowledge()没有';在使用Spring Boot在ActiveMQ中读取消息后,t将消息出列

为什么Java编译器为没有参数的方法(getter方法)创建桥接方法