Java 以这种方式构造对象是否非常规?(关于同一个构造器的几个问题)

Java 以这种方式构造对象是否非常规?(关于同一个构造器的几个问题),java,multithreading,oop,constructor,static,Java,Multithreading,Oop,Constructor,Static,我发现线程对象通常可以以这种方式创建和跟踪: ArrayList<MyThreadClass> threads = new ArrayList<>(); MyThreadClass myThread = new Thread(); myThread.start(); threads.add(myThread); 也许我还没有找到正确的代码示例,但我很少(如果有的话)看到这种使用构造函数生成对象和存储其引用的方法。我想知道使用列出的两种情况中的任何一种是否非常规和/或不

我发现
线程
对象通常可以以这种方式创建和跟踪:

ArrayList<MyThreadClass> threads = new ArrayList<>();

MyThreadClass myThread = new Thread();
myThread.start();
threads.add(myThread);
也许我还没有找到正确的代码示例,但我很少(如果有的话)看到这种使用构造函数生成对象和存储其引用的方法。我想知道使用列出的两种情况中的任何一种是否非常规和/或不切实际,以及其中是否有任何一种会导致错误

这样做是否不合常规/不切实际:

  • 使用
    new MyClass()
    而不存储返回的引用
  • 使用构造函数中的
    this
    关键字将实例添加到列表中
  • 从它的(子)构造函数中启动一个
    线程
  • 在实例的构造函数完成之前引用实例会导致问题吗?(在这种情况下,在构造函数本身内)

这在很大程度上与风格和品味有关。但是,(2)到(4)在多线程上下文中要求特别注意,因为在当前线程完全完成构造之前,另一个控制流可能会访问正在构造的对象。因此,只有在建立了对象的一致状态时(例如,在构造函数的最末端),才泄漏引用。请确保使用一个唯一的锁正确地同步(2)中使用的数据结构,例如,锁定自身或包含的类对象。

这在很大程度上取决于风格和品味。但是,(2)到(4)在多线程上下文中要求特别注意,因为在当前线程完全完成构造之前,另一个控制流可能会访问正在构造的对象。因此,只有在建立了对象的一致状态时(例如,在构造函数的最末端),才泄漏引用。确保使用单个唯一锁(例如,自身或包含类对象上的锁)正确同步(2)中使用的数据结构

  • 是否使用新的MyClass()而不存储返回的引用
  • 这有点奇怪,除非您立即调用该引用上的方法-这意味着构造函数有副作用;通常,您应该尽量避免构造函数中的副作用

    这里的副作用是将实例添加到
    静态
    列表中;我强烈建议不要那样做。这是一种可变的全局状态,可能会导致各种难以调试的问题,以及可测试性的降低

    最好有一个工厂来创建
    连接
    实例,并将其添加到“工厂创建的实例”列表中:

    类连接工厂{
    列出创建的状态;
    连接createInstance(套接字){
    连接实例=新连接(套接字);
    createdInstances.add(实例);
    返回实例;
    }
    }
    
  • 使用其构造函数中的this关键字将实例添加到列表中
  • 那么这跟

  • 在实例的构造函数完成之前引用实例会导致问题吗?(在这种情况下,在构造函数本身内)
  • 如果答案是是,它可能会导致一系列问题,尤其是在多线程代码中使用实例时。我建议您在实践中阅读Java并发性,它彻底解决了与泄漏对部分初始化对象的引用相关的问题

  • 从它的(子)构造函数中启动线程
  • 这是一个“在构造函数中做太多工作”的例子,这是一个错误

  • 是否使用新的MyClass()而不存储返回的引用
  • 这有点奇怪,除非您立即调用该引用上的方法-这意味着构造函数有副作用;通常,您应该尽量避免构造函数中的副作用

    这里的副作用是将实例添加到
    静态
    列表中;我强烈建议不要那样做。这是一种可变的全局状态,可能会导致各种难以调试的问题,以及可测试性的降低

    最好有一个工厂来创建
    连接
    实例,并将其添加到“工厂创建的实例”列表中:

    类连接工厂{
    列出创建的状态;
    连接createInstance(套接字){
    连接实例=新连接(套接字);
    createdInstances.add(实例);
    返回实例;
    }
    }
    
  • 使用其构造函数中的this关键字将实例添加到列表中
  • 那么这跟

  • 在实例的构造函数完成之前引用实例会导致问题吗?(在这种情况下,在构造函数本身内)
  • 如果答案是是,它可能会导致一系列问题,尤其是在多线程代码中使用实例时。我建议您在实践中阅读Java并发性,它彻底解决了与泄漏对部分初始化对象的引用相关的问题

  • 从它的(子)构造函数中启动线程

  • 这是一个“在构造函数中做太多工作”的例子,这是一个很好的例子。

    有关codereview,请访问codereview.stackexchange.com。我的简短评论是:很多坏主意。静态可能非常危险,因为它会使代码测试变得非常困难。然后:构造函数应该只构造对象。。。您可能希望将其与启动线程等“实际操作”分离。长话短说:例如,你想读一读。然后,您需要练习TDD,以便提出一个实际上是可单元测试的设计……我投票将这个问题作为离题题结束,因为它属于codereview.stackexchange。com@J关于codereview的ägermeister:我不是要求人们分析我的代码,我有v
    class Connection{
        private static ArrayList<Connection> clients = new ArrayList<>();
        MyListener listener; //extends Thread
    
        Connection(Socket s){
            listener = new MyListener(s)
            listener.start();
            clients.add(this);
        }
    }
    
    while(true){
        //try/catch blocks excluded here for the sake of simplicity
        new Connection(serverSocket.accept());
    }
    
    class ConnectionFactory {
      List<Connection> createdInstances;
    
      Connection createInstance(Socket socket) {
        Connection instance = new Connection(socket);
        createdInstances.add(instance);
        return instance;
      }
    }