相关疑难解决方法(0)

为什么返回Java对象引用比返回原语要慢得多

我们正在开发一个对延迟敏感的应用程序,并已对所有类型的方法进行微基准测试(使用jmh).在对查找方法进行微基准测试并对结果感到满意之后,我实现了最终版本,但却发现最终版本比我刚刚基准测试的版本3倍.

罪魁祸首是实现的方法返回一个enum对象而不是一个int.以下是基准代码的简化版本:

@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Thread)
public class ReturnEnumObjectVersusPrimitiveBenchmark {

    enum Category {
        CATEGORY1,
        CATEGORY2,
    }

    @Param( {"3", "2", "1" })
    String value;

    int param;

    @Setup
    public void setUp() {
        param = Integer.parseInt(value);
    }

    @Benchmark
    public int benchmarkReturnOrdinal() {
        if (param < 2) {
            return Category.CATEGORY1.ordinal();
        }
        return Category.CATEGORY2.ordinal();        
    }


    @Benchmark
    public Category benchmarkReturnReference() {
        if (param < 2) {
            return Category.CATEGORY1;
        }
        return Category.CATEGORY2;      
    }


    public static void main(String[] …
Run Code Online (Sandbox Code Playgroud)

java low-latency jmh

73
推荐指数
2
解决办法
5327
查看次数

Java中的构造函数同步

有人告诉我,Java构造函数是同步的,因此在构造期间无法同时访问它,我想知道:如果我有一个构造函数将对象存储在一个映射中,另一个线程在构造之前从该映射中检索它完成后,该线程会阻塞,直到构造函数完成?

让我演示一些代码:

public class Test {
    private static final Map<Integer, Test> testsById =
            Collections.synchronizedMap(new HashMap<>());
    private static final AtomicInteger atomicIdGenerator = new AtomicInteger();
    private final int id;

    public Test() {
        this.id = atomicIdGenerator.getAndIncrement();
        testsById.put(this.id, this);
        // Some lengthy operation to fully initialize this object
    }

    public static Test getTestById(int id) {
        return testsById.get(id);
    }
}
Run Code Online (Sandbox Code Playgroud)

假设put/get是地图上唯一的操作,所以我不会通过迭代之类的东西获得CME,并试图忽略其他明显的缺陷.

我想知道的是,如果另一个线程(显然不是那个构造对象的线程)尝试使用getTestById并调用它上面的东西来访问该对象,它会阻塞吗?换一种说法:

Test test = getTestById(someId);
test.doSomething(); // Does this line block until the constructor is done?
Run Code Online (Sandbox Code Playgroud)

我只是想弄清楚构造函数同步在Java中走了多远,以及像这样的代码是否有问题.我最近看过像这样的代码,而不是使用静态工厂方法,我想知道这在多线程系统中是多么危险(或安全).

java concurrency multithreading constructor

19
推荐指数
3
解决办法
1万
查看次数

JMM保证最终为对象的字段和非最终引用

我尝试理解最终字段的语义.

让研究代码:

public class App {

    final int[] data;
    static App instance;

    public App() {
        this.data = new int[]{1, 0};
        this.data[1] = 2;
    }


    public static void main(String[] args) {
        new Thread(new Runnable() {
            public void run() {
                instance = new App();
            }
        }).start();

        while (instance == null) {/*NOP*/}
        System.out.println(Arrays.toString(instance.data));
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一些问题:

  1. jmm是否保证,如果应用程序终止,那么它输出[1,2]?
  2. jmm是否保证在循环终止后instance.data不为null?

PS我不知道如何使标题正确,随时编辑.

额外

如果我们更换,是否有可见性差异:

public App() {
    this.data = new int[]{1, 0};
    this.data[1] = 2;
}
Run Code Online (Sandbox Code Playgroud)

public App() {
    int [] data …
Run Code Online (Sandbox Code Playgroud)

java concurrency visibility final java-memory-model

4
推荐指数
1
解决办法
195
查看次数

为什么在实践书中将并发的SafePoint类标记为@ThreadSafe?

在《 Java并发实践》一书中,您可以找到以下代码:

@ThreadSafe
public class SafePoint { 
    @GuardedBy("this") private int x, y;
    private SafePoint(int[] a) { this(a[0], a[1]); }
    public SafePoint(SafePoint p) { this(p.get()); }
    public SafePoint(int x, int y) { 
        this.x = x;
        this.y = y;
    }
    public synchronized int[] get() { return new int[] { x, y };
    }
    public synchronized void set(int x, int y) { this.x = x;
        this.y = y;
    }
}
Run Code Online (Sandbox Code Playgroud)

此标记为 @ThreadSafe

我很确定此类不是线程安全的(如果我正确理解了这个术语的话)。

例:

 SafePoint racePublishedSafePoint; // field

 // thread 1:
 racePublishedSafePoint …
Run Code Online (Sandbox Code Playgroud)

java concurrency multithreading thread-safety

4
推荐指数
1
解决办法
164
查看次数