Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java类中的单个静态字段_Java_Multithreading_Static_Synchronized - Fatal编程技术网

Java类中的单个静态字段

Java类中的单个静态字段,java,multithreading,static,synchronized,Java,Multithreading,Static,Synchronized,有一个类RedisLogger.java,用于处理带有redis的记录器。在RedisLogger.java中,我使用以下代码声明了一个静态JedisPool字段JedisPool: private static JedisPool jedisPool; 由于JedisPool是线程安全的CALS,我想使用以下代码在我的应用程序中仅实例化一次JedisPool: public static JedisPool getJedisPool() { if(jedisPool == null)

有一个类RedisLogger.java,用于处理带有redis的记录器。在RedisLogger.java中,我使用以下代码声明了一个静态JedisPool字段
JedisPool

private static JedisPool jedisPool;
由于JedisPool是线程安全的CALS,我想使用以下代码在我的应用程序中仅实例化一次
JedisPool

public static JedisPool getJedisPool() {
    if(jedisPool == null) {
        synchronized (JedisPool.class) {
            if(jedisPool == null) {
                jedisPool = new JedisPool();
            }
        }
    }
    return jedisPool;
}
我用这个代码来测试它

ExecutorService executor = Executors.newCachedThreadPool();
    for(int i = 0; i < 1000; i++) {
        executor.execute(()->{
            System.out.println(RedisLogger.getJedisPool());
        });
    }
但它真的能达到我的期望吗? 因为在我的申请表中有很多类似的地方。比如说

private static Cluster getCluster() {
    if(cluster == null) {
        synchronized (Cluster.class) {
            if(cluster == null) {
                Builder builder = Cluster.builder();
                for (int i = 0; i < MSConfig.SRCDOC_CASSANDRA_ADDRS().length; i++) {
                    builder.addContactPoint(MSConfig.SRCDOC_CASSANDRA_ADDRS()[i])
                            .withPort(MSConfig.SRCDOC_CASSANDRA_PORT()[i]);
                }
                cluster = builder.withCredentials(MSConfig.SRCDOC_CASSANDRA_USERNMAE(), MSConfig.SRCDOC_CASSANDRA_PASSWORD())
                        .withProtocolVersion(ProtocolVersion.V4)
                        .withPoolingOptions(getPoolingOptions())
                        .withSocketOptions(getSocketOptions())
                        .withRetryPolicy(getRetryPolicy())
                        .withQueryOptions(getQueryOptions())
                        .build();
            }
        }
    }
    return cluster;
}
private静态集群getCluster(){
if(cluster==null){
已同步(Cluster.class){
if(cluster==null){
Builder=Cluster.Builder();
对于(int i=0;i

谢谢

您可以直接为变量赋值,并在案例中声明它为
final static

我想到的唯一的增加是放弃
同步化
初始化,直接使用。从:

JVM推迟初始化InstanceHolder类,直到它实际被使用为止,并且由于Singleton是用静态初始值设定项初始化的,不需要额外的同步

这可以在您的代码中使用,如下所示:

public class RedisLogger{
     public static JedisPool getJedisPool(){
         return JedisPoolHolder.INSTANCE;
     }

     private static final class JedisPoolHolder{
         private static final JedisPool INSTANCE = new JedisPool();
     }

     // the rest of your code
}

您所做的工作称为“双重检查锁定”。如果你在Stackoverflow或Google上搜索这个,你会发现很多解释,解释为什么它在Java中不能正常工作

备选方案是:

  • 如果很有可能在加载该对象的保持类时使用该对象,则直接初始化该对象并使该字段成为最终字段
  • 声明字段
    为volatile
  • 使用holding类,即拥有一个私有的内部类来保存字段,然后将字段设置为final
  • 另见以下问题:


    静态
    是使某事物成为单一事物的关键字
    final
    仅说明变量的值不能更改。因此,您目前的答案是错误的,它不一定是关于单例的,但是在这个上下文中final会很好,因为我们不想修改这个值,所以因为它将在声明期间赋值,所以它可以是final。虽然编辑了我的答案。但是你仍然需要
    static
    一点误解。我的意思是在修改器中添加final,而不是用final替换它们。谢谢你的编辑。因为它是一个池,我想它会被修改。。。我不认为
    final
    就在这里,但它真的能达到我的期望吗。应该这样。为什么不应该呢?你看到不一致吗?我们不知道您的代码,所以我们无法通过查看您的最后一个代码片段来判断它是否有效。我们需要完整的图片,但这会打破这个问题的框架。我知道,双重检查用于单例模式。但我想将其用于一个字段。您当前拥有的代码可能会泄漏未初始化的
    JedisPool
    实例。这与单身汉无关。
    public class RedisLogger{
         public static JedisPool getJedisPool(){
             return JedisPoolHolder.INSTANCE;
         }
    
         private static final class JedisPoolHolder{
             private static final JedisPool INSTANCE = new JedisPool();
         }
    
         // the rest of your code
    }