【问题标题】:static method vs singleton methods in multithreaded environment多线程环境中的静态方法与单例方法
【发布时间】:2015-09-29 06:56:34
【问题描述】:

我有一个包含静态方法和单例类的代码示例

//code with static methods
public class DataManager{
  public static Object getDataObject(){
     HashMap map = new HashMap();
     //Some processing in collections
     //retrieval of data
  }
  public static void writeData(Object o){
     HashMap map = new HashMap();
     //Some processing in collections
     //writing data
  }
}
//code with singleton
public class DataManager{
   private static DataManager instance;
   private DataManager(){
   }
   public static DataManager getInstance(){
     if(instance == null){
        synchronized(DataManager.class){
          if(instance == null){
              instance = new DataManager();
          }
       }
    }
    return instance;
  }
  public Object getDataObject(){
     HashMap map = new HashMap();
     //Some processing in collections
     //retrieval of data
  }
  public writeData(Object o){
     HashMap map = new HashMap();
     //Some processing in collections
     //writing data
  }
}

这是最好的使用方式。 当 2 个线程调用我的方法之一时会发生什么?在处理集合时,我的数据是否会损坏?静态方法分配了公共内存,所以当2个线程调用一个静态方法时会相互影响吗?在单例中只创建一个实例,如果 2 个线程用一个实例调用一个方法,它会相互影响吗?请帮助理解这一点。谢谢...

【问题讨论】:

  • 坦率地说,你需要用谷歌搜索一下。多线程不能这样解释
  • @Lathy 所以地图对象是共享的,那么当 2 个线程使用这个地图时,数据可能会损坏。对吗?

标签: java concurrency singleton static-methods singleton-methods


【解决方案1】:

从不同的线程调用静态方法不会破坏任何东西......除非方法正在使用/更改共享实例或静态变量,但在这种情况下,所有方法都是如此,而不仅仅是具有静态性质的方法。
这不是第一次有人对此感到困惑......请谷歌它或在 Stackoverflow 中搜索类似的问题。这个问题被多次回答。

【讨论】:

    【解决方案2】:

    无论您使用静态方法还是单例都不会影响线程安全。您的代码可能是线程安全的,也可能不是,这取决于您执行的处理类型。 (如图所示,您的代码是线程安全的,因为映射是在 getDataObjectwriteData 方法的本地创建的,因此不会在不同线程之间共享。)

    一般来说,如果不同的线程不会同时访问相同的数据,那么代码就是线程安全的。此外,如果一个对象是只读的,多个线程可以同时读取它而不会破坏线程安全。一旦一个线程修改了共享数据,您就必须同步对它的访问。

    【讨论】:

    • 即使我使用一些其他的集合和其他类的对象来处理数据,数据不会有任何损坏吗?在内存方面解释它,它为每个线程存储在哪里以及数据如何不会被破坏。
    • 我写道:“您的代码可能是线程安全的,也可能不是,取决于您执行的处理类型。”所以,当然,如果您访问其他数据,那么它可能不是线程安全的。但是问题中的代码只包含cmets。
    • getDataObject(){ HashMap map = new HashMap();查询查询 = QueryBuilder.select(map); ResultSet 结果 = query.execute();返回结果.parseResult;像这样的一些代码将在那里而不是 cmets
    • 您的数据库通常是线程安全的。因此,这取决于您在实际代码中使用该哈希映射做什么。如果你只在你的方法中使用它,它就不是一个共享对象,也不会破坏线程安全。
    【解决方案3】:

    根据我对多线程的理解,它是一个共享对象,可以被多个线程访问。

    因此,在您的两个程序中,地图对象都是共享实例,将被多个线程访问。所以你应该同步地图对象以保证线程安全。

    Singleton 或 Static 与此无关

    【讨论】:

    • 我不同意你的回答。 Map 对象是本地方法,将在线程自己的堆栈上。没有一个类具有共享状态。
    猜你喜欢
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 2012-11-12
    相关资源
    最近更新 更多