Java 单身班不起作用

Java 单身班不起作用,java,singleton,Java,Singleton,我试图使客户机类成为单例,但它不起作用。这是我的班级: public class Clients { private static Clients instance = null; private ArrayList<Client> cList; private Clients() { cList = new ArrayList<Client>(); } public static Clients getInst

我试图使
客户机
类成为单例,但它不起作用。这是我的班级:

public class Clients {
    private static Clients instance = null;
    private ArrayList<Client> cList;

    private Clients() {
        cList = new ArrayList<Client>();
    }

    public static Clients getInstance() {
        if (instance == null) {
            System .out.println("created");
            instance = new Clients();
        }

        return instance;
    }

    public static ArrayList<Client> getcList() {
        return getInstance().cList;
    }

    public static void setcList(ArrayList<Client> cList) {
        getInstance().cList = cList;
    }
}
公共类客户端{
私有静态客户端实例=null;
私人ArrayList cList;
私人客户(){
cList=newarraylist();
}
公共静态客户端getInstance(){
if(实例==null){
System.out.println(“已创建”);
实例=新客户端();
}
返回实例;
}
公共静态数组列表getcList(){
返回getInstance().cList;
}
公共静态void setcList(ArrayList cList){
getInstance().cList=cList;
}
}

我在两个不同的类中得到这个实例(都有自己的主函数)。在一个类中得到它的实例后,我在另一个类中得到它,但这两个类仍然在执行。

每当实现一个单例时,
getInstance()
方法应该是线程安全的

e、 g

。。。或者

private static final Object INSTANCE_LOCK = new Object();

public static Clients getInstance() {
    synchronized(INSTANCE_LOCK) {
        if(instance == null) instance = new Clients();
    }
    return instance;
}
当然,如果您实际上是从两个不同的程序而不是两个不同的线程执行这段代码,那么您将有两个实例。我假设前者,因为后者使你的问题变得毫无意义

我想我应该解释为什么那是荒谬的


当您使用
main(String[]args)
方法执行Java程序时,所有类都会加载到JVM中。如果执行另一个程序,则会得到另一个JVM和所有关联类的另一个“副本”。因此,您有两个单独的单例——每个程序一个。这两个类之间不共享类。

您提到这两个类“都有自己的main”,所以我假设您有两个独立的程序

长话短说,两个程序之间并没有真正共享数据。singleton类将确保在单个程序中只有该对象的一个实例,但两个程序仍然完全独立,不能以这种方式共享数据

即使只有一个类带有“main”并且只运行了两次,情况也是如此

如果您想在这样的程序之间共享数据,您有很多选择,但有些是:

  • 看看你是否能把两个独立的程序合并成一个。你真的需要两个程序吗
  • 使用数据库来存储数据,MySQL和SQLite是两个简单的选项,在许多选项中
  • 一个程序可以将数据写入文件,另一个程序可以读取数据
  • 还有许多其他选项可以将数据从一个程序发送到另一个程序,例如套接字(已经存在大量网络协议,而且您可以自己使用)、特定于平台的东西,如Windows上的命名管道、共享内存等。请查看谷歌搜索结果以了解更多信息(进程间通信——这是允许两个程序相互通信的一般技术)

你只要做一件事就可以解决很多问题

私有静态客户端实例=新客户端()

不必担心get实例中的锁定习惯用法。除非您正在构建的类的构建成本很高,否则进行这种惰性实例化是没有意义的

话虽如此,我也不确定我是否喜欢cList的getter和setter。我更希望这些方法成为您正在创建单例的类上的实例方法,因此您可以这样做(例如)


而且,如果这是一个多线程环境,那么您必须意识到setter可能会影响已经引用singleton对象的其他线程。

您可以如上所述使用同步块,但您可能还需要考虑使用锁

关于锁最好的一点是synchronized关键字不提供公平性,而我们可以在创建ReentrantLock对象时将公平性设置为true,以便等待时间最长的线程首先获得锁

// Fairness set to false is faster than a synchronized block.
private static final ReentrantLock rlock = new ReentrantLock(false);

public static final Clients getInstance() {
    rlock.lock();
    try {
        System.out.printf("[Thread %s] Clients.getInstance()%n",
            Thread.currentThread().getName());
        if (instance == null) {
            instance = new Clients();
        }

        return instance;
    } finally {
        rlock.unlock();
    }    
}

你是从多个线程访问的吗?你想实现什么?另外,你提到两个类都有自己的main方法。这是否意味着你运行两个单独的程序来访问单例?如果是这样,单例不会扩展到特定的进程边界。我很困惑。你是在两个类中进行的,并且都有自己的主方法main函数;这是否意味着您正在编译和运行两个不同的程序?在多线程应用程序中,这可能是一个很好的建议,但这里似乎没有提到线程?@JasonC是的,我假设他指的是两个线程,而不是两个程序,因为后者让问题变得毫无意义,哈哈。也许。。。虽然对于初学者来说,如果他的目标(似乎是一个秘密)是合理的,那么误解单例并认为实例在程序之间共享是合理的是在两个同时运行的程序之间共享数据。可重入锁呢?抱歉!!!我的错。我正在运行两个不同的程序'我明白你的意思,但我在cList中有客户端套接字,我无法将其存储在db或文件中,,,,,因此,你能告诉我一个解决方案,以获取任何客户端中所有其他客户端套接字的列表吗thread@UmerSufy您不能在Java中的程序之间共享套接字本身。您能提供一点关于您正在尝试执行的操作的详细信息吗?听起来可能有更好的方法,但在不了解您的应用程序的情况下,不可能给您提供任何更可靠的建议。您的两个单独的程序实际上做什么?这就开始了听起来有点像。!关于XY问题,你是对的。我正在制作一个聊天服务器。我想向任何特定的客户端发送一个客户端列表,以便它可以选择任何其他客户端进行聊天。我正在与我的朋友讨论这个问题,现在我只发送Inetaddress和port,现在我将使用UDP在客户端之间进行通信。(我以前使用过TCP。)这是正确的方法吗?我以前从未见过有人使用
进行用户链接
Clients clients = Clients.getInstance();
clients.getcList();
// Fairness set to false is faster than a synchronized block.
private static final ReentrantLock rlock = new ReentrantLock(false);

public static final Clients getInstance() {
    rlock.lock();
    try {
        System.out.printf("[Thread %s] Clients.getInstance()%n",
            Thread.currentThread().getName());
        if (instance == null) {
            instance = new Clients();
        }

        return instance;
    } finally {
        rlock.unlock();
    }    
}