java - 构造函数是否同步直至完全完成?

标签 java multithreading constructor synchronized

我正在构建一个程序,需要构建一些需要如此密集的计算才能创建的对象,我最明智的做法是将它们构建在自己的专用线程中,而主线程则不断地处理其他事情,直到需要这些对象。

所以我考虑创建一个特殊的类,专门用于在自己的线程中创建自定义对象。就像这样:

public abstract class DedicatedThreadBuilder<T> {

    private T object;

    public DedicatedThreadBuilder() {
        DedicatedThread dt = new DedicatedThread(this);
        dt.start();
    }

    private void setObject(T i) {
        object = i;
    }

    protected abstract T constructObject();

    public synchronized T getObject() {
        return object;
    }

    private class DedicatedThread extends Thread {

        private DedicatedThreadBuilder dtb;

        public DedicatedThread(DedicatedThreadBuilder builder){
            dtb = builder;
        }

        public void run() {
            synchronized(dtb) {
                dtb.setObject(dtb.constructObject());
            }
        }

    }

}

我唯一担心的是,只有当主线程(即构造 DedicatedThreadBuilder 的线程)在 DedicatedThreadBuilder 上拥有同步锁时,此机制才能正常工作,直到它构造已完成,因此会阻止 DedicatedThread 尝试构造产品对象,直到它完成 DedicatedThreadBuilder 的构造。为什么?因为DedicatedThreadBuilder的子类无疑需要使用参数进行构造,因此需要将其传递到它们自己的私有(private)存储中,以便它们可以在constructObject()中使用> 过程。

例如

public class JellybeanStatisticBuilder extends DedicatedThreadBuilder<JellybeanStatistics> {

    private int greens;
    private int blacks;
    private int yellows;

    public JellybeanStatisticBuilder(int g, int b, int y) {
        super();
        greens = g;
        blacks = b;
        yellows = y;
    }

    protected JellybeanStatistics constructObject() {
        return new JellybeanStatistics(greens, blacks, yellows);
    }

}

只有在对象完全构造完成之前,该对象被其他线程阻塞时,此方法才能正常工作。否则,DedicatedThread可能会在分配必要的变量之前尝试构建对象。

这就是 Java 的工作原理吗?

最佳答案

我认为你想要的是某种同步工厂类:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

public class SyncFactory<T> {    
    // alternatively, use newCachedThreadPool or newFixedThreadPool if you want to allow some degree of parallel construction
    private ExecutorService executor = Executors.newSingleThreadExecutor();

    public Future<T> create() {        
        return executor.submit(() -> {
            return new T();
        });
    }
}

现在您将替换 T 的用法这可能需要在 T 之前发生已准备好 Future<T> ,并可以选择调用其 Future.get()方法阻塞直到准备好、设置超时或调用 Future.isDone()检查施工情况,不堵塞。此外,您可能希望让工厂在完成构造时调用回调或发布事件来通知主线程,而不是轮询 Future。

关于java - 构造函数是否同步直至完全完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53213866/

相关文章:

java - 为什么要在 invokeAll 方法之后调用 join 呢?

iphone - 循环 MPMoviePlayerController 视频时可能出现线程问题

java - 获取套接字数据后调用单独的线程进行进一步处理?

c# - 在 C# 中,是否需要调用基类构造函数?

java - 尝试使用非静态方法引用非静态字段会导致错误

Java:replace() 以正则表达式结尾的 n 管道分隔符

java - 写入和读取文件后字符串发生变化

c++ - 如果我声明解构函数但与默认解构函数完全相同,编译器是否仍会生成默认移动构造函数?

java - 如何在 java 中为 ValueRange 变量赋值?

ruby-on-rails - 使用 Action 电缆时如何使状态保持一致