【问题标题】:store data in Singleton classes在 Singleton 类中存储数据
【发布时间】:2011-05-19 13:54:13
【问题描述】:

我在 java 中有一个应用程序,它使用两个不同的线程。为了在这两个线程之间共享数据,我想使用 Singleton 类。

线程间需要共享的数据是(Latitude,Longitude)。

这是我的问题:我应该使用什么来将这些数据存储在 Singleton 类中?

一些列表..?

如果你也能提供一个例子,那就太棒了。谢谢!

这是单例吗????我怎样才能使它成为非单例

编辑:

我有一个执行以下操作的 java 应用程序:

1.第一个线程(它是一个ThreadPool)——我相信它也会写在BlockingQ中 侦听一个端口以接收来自五个不同用户的传入连接 让我们称呼他们:

用户1 用户2 用户3 用户4 用户5

他们每个人都在发送 GPS 数据。

2.第二个线程——将从 BlockingQ 中读取。 同时,我的 Java 应用程序监听第二个端口,等待另一个客户端(不同于发送 GPS 数据的客户端)连接到它。

现在...我有第二个应用程序连接到我刚刚描述的 java 应用程序。

在第二个应用程序中,我有一个列表 user1...user5 并根据我将选择的项目(user1...5)我必须从那里接收正确的数据。

所以现在....我如何在 BlockingQ 中写入/读取数据才能接收正确的数据???

【问题讨论】:

  • 在程序执行期间你的数据会改变吗?如果是,建议使用同步方法。
  • 一个线程将数据写入类,另一个线程从那里读取数据。但也想存储该数据,因为,是的,它发生了变化。我需要存储它,当读取线程可用时,他可以读!
  • @embry:首先您需要构建一个线程安全的单例 (jguru.com/faq/view.jsp?EID=124425) 以避免之后有两个单例,在从单例获取和设置值时应该使用类似的方法...锁定包含值的对象
  • 我做到了;)...现在下一步是什么?
  • @Amine - ..或者他可以把所有的 greif 都省下来,而不是让它成为一个单身人士。

标签: java latitude-longitude


【解决方案1】:

我认为您要实现的是生产者消费者模式。为此,您应该使用 BlockingQueue 和带有纬度和经度的不可变 Coordinate 对象。

Coordinate 应该只有两个字段 Longitude 和 Latitude 这两个字段都是 final 字段并且只能使用构造函数设置。通过这种方式,您可以确保您没有任何竞争条件或使用错误的线程意外更改字段。

BlockingQueue 不会永久存储数据,因此只有如果您需要这样做,您可以创建一个 Singleton。
更好的解决方案 将创建一个像 ShareData 这样的类并将它们传递给两个线程,这样您就可以节省一些时间来创建线程安全的 Singleton。这可能看起来像这样:

public interface ShareData {
    public void AddToList(Coordinate coord); // add to BlockingQueue and an internal store here
    public Coordinate TakeFromList();  // take from BlockingQueue
}

Coordinate 类应该如下所示并且是线程安全的,因为它是不可变的并且无法更改其值。

public class Coordinate {
  private final double lon;
  private final double lat;

  public Coordinate(double lon, double lat) {
    this.lon = lon;
    this.lat = lat;
  }

  public double getLon() {
    return lon;
  }

  public double getLat() {
    return lat;
  }
}

【讨论】:

  • 好吧,我不是很高级,但我有这样一门课....单身到底意味着什么。我会用代码编辑我的问题。
  • 看看这里顶部的示例:download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/…。基本上,此示例向您展示了一个应用程序,其中 1 个线程正在生成对象,2 个线程正在使用生成的对象。您应该能够通过添加一个 Coordinate 类来使这个简单的示例适应您的程序(我编辑我的答案)
  • 基本方法是正确的,但您不要为此使用 SINGLETON。您使用一个普通对象并在启动它们时将其作为参数提供给两个线程。 (所以你可以使用你的类有很多对线程)
  • 不要使用单例,而是使用BlockingQueue!这就是我们想告诉你的:)
  • @Simon 但是你刚才说我的 BlockingQueue 不会永久存储数据!:“BlockingQueue 不会永久存储数据,所以只有当你需要这样做时,你才应该创建一个可以看起来像这样:...”
【解决方案2】:

我的建议是不要打扰单身人士。 Singletons are almost never a good idea.如果你不想要超过一个,就不要制作超过一个。如果您希望它是全局的,请将您的一个对象声明为全局类(但更好的是,只需选择一个类来拥有它。)。

我不了解您的程序,但我很有可能您将永远看到由于某人无意中创建了多个共享数据类对象而导致的错误。但是,正确编码线程安全的单例是一个非常棘手的问题,如果您尝试这样做,您很可能会遇到错误。

当你发现由于某种原因需要另一对这样的通信线程时会发生什么?当然,您希望这些共享数据对象中的另一个与它们一起使用,但是由于您将其设为单例,因此它成为该类的主要重写,而不是琐碎的事情。

【讨论】:

    【解决方案3】:

    只需创建一个类来存储该信息。 lat/lon 可以用双精度表示。

    public class OuterClass {
        public static synchronized InnerSingleton getSingleton() {
            if(singleton == null) {
                singleton = new InnerSingleton();
            }
            return singleton;
        }
    
        private InnerSingleton singleton;
    
        class InnerSingleton {
            private double lat, lon;
            private InnerSingleton() { }
            public double getLatitude() { return lat; }
            public double getLongitude() { return lon; }
            public void setLatitude(double l) { lat = l; } //maybe validate? -90 <= lat <= 90
            public void setLongitude(double l) { lon = l; } //maybe validate? -180 <= lon <= 180
       }
    
    }
    

    【讨论】:

    • 是的,我想过这个。但是一旦新信息进入旧信息就会丢失。我的问题是使用什么来存储 (lat,lon) 以免丢失它?缓冲区也许?
    • 它根本不是线程安全的,非易失性成员会导致一些写入无法通过......等等
    • 我知道这只是一个玩具示例,但正如所展示的那样,这将我最大的两个讨厌的东西合二为一:单身人士(以及针对特定目的的不安全的人)和一个否则什么都不是的类但是对于私人成员来说是赤裸裸的二传手。这个类基本上是一个带有可怕的拿破仑情结的 C struct
    【解决方案4】:

    我建议使用并发队列

    java.util.concurrent 中查找可以帮助您的几个实现:ConcurrentLinkedQueue、ConcurrentBlockingQueue

    所以你有一个单例队列,一个线程读取另一个线程写入

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-10
      • 2016-03-31
      • 1970-01-01
      相关资源
      最近更新 更多