我们正在开发一个对延迟敏感的应用程序,并已对所有类型的方法进行微基准测试(使用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构造函数是同步的,因此在构造期间无法同时访问它,我想知道:如果我有一个构造函数将对象存储在一个映射中,另一个线程在构造之前从该映射中检索它完成后,该线程会阻塞,直到构造函数完成?
让我演示一些代码:
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中走了多远,以及像这样的代码是否有问题.我最近看过像这样的代码,而不是使用静态工厂方法,我想知道这在多线程系统中是多么危险(或安全).
我尝试理解最终字段的语义.
让研究代码:
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)
我有一些问题:
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并发实践》一书中,您可以找到以下代码:
@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)