Singleton类不起作用

时间:2014-03-28 21:39:36

标签: java singleton

我试图制作Clients类单身人士,但它无效。这是我的班级:

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;
    }
}

我在两个不同的类中获得此实例(两者都有自己的主函数)。在一个类中获取它的实例后,我在另一个类中获取它,但两个tiare仍在执行。

4 个答案:

答案 0 :(得分:4)

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

如,

public static synchronized Clients getInstance()

......或......

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和另一个&#34; copy&#34;所有相关课程。因此,你有两个单独的单身 - 每个程序一个。两个人之间没有分享课程。

答案 1 :(得分:4)

你提到两个班级“都有自己的主”,所以我假设你有两个独立的课程。

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

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

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

  • 看看你是否真的可以将两个独立的程序合二为一。你真的需要两个程序吗?
  • 使用数据库存储您的数据,MySQL和SQLite是两个简单的选项,其中很多。
  • 一个程序可以将数据写入文件,另一个程序可以读取它。
  • 还有许多其他选项可以将数据从一个程序发送到另一个程序,例如套接字(已经有很多网络协议,你可以自己动手),特定于平台的东西,如Windows上的命名管道,共享检查"java ipc"的Google搜索结果(进程间通信 - 这些是允许两个程序相互通信的一般技术)。

答案 2 :(得分:0)

只需执行

即可摆脱许多问题

private static Clients instance = new Clients()

无需担心get实例中的锁定习惯用法。除非你正在构建的类构建起来很昂贵,否则进行这种惰性实例化是没有意义的。

话虽如此,我不确定我是否喜欢cList的getter和setter。我更喜欢这些是你正在制作单身的类的实例方法,所以你要做(例如)

Clients clients = Clients.getInstance();
clients.getcList();

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

答案 3 :(得分:0)

您可以使用上面的 Jeff Gohlke 声明的同步块,但您可能还想查看使用锁。

关于锁的最好的事情是 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();
    }    
}