简体   繁体   English

可以在Java中简化此并发代码

[英]Can this concurrent code be simplified in Java

I have the following use case: my Android application makes multiple concurrent HTTP requests to the server. 我有以下用例:我的Android应用程序向服务器发出多个并发HTTP请求。 If a request produces "Incorrect token" error then the application should regenerate the token by making a special request to the server and repeat the failed request. 如果请求产生“不正确的令牌”错误,则应用程序应通过向服务器发出特殊请求并重复失败的请求来重新生成令牌。

As there are multiple concurrent requests that produce the same error and token should be generated only once I used the following construct: 由于有多个并发请求产生相同的错误,因此只有在使用以下构造时才应生成令牌:

static final AtomicBoolean isTokenSync = new AtomicBoolean(false);
private static CountDownLatch countDownLatchTokenSync;

if (isTokenSync.compareAndSet(false, true)) {
        countDownLatchTokenSync = new CountDownLatch(1);

        generateAndSaveToken(...);

        isTokenSync.set(false);   
        countDownLatch.countDown();
    }
    else {
        try {
            countDownLatch.await(5, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
        }
    }
}

// repeat the request

Basically first thread gets through and generates the token and other threads wait until token generated and proceed. 基本上第一个线程通过并生成令牌,其他线程等待,直到令牌生成并继续。 Is my code a good approach to achieve the behavior? 我的代码是实现这种行为的好方法吗? Can it be simplified? 可以简化吗?

You can use a Phaser here nicely. 你可以在这里使用Phaser It's like a CyclicBarrier that supports a dynamic number of waiting parties for all threads arriving at a phase. 它就像一个CyclicBarrier ,支持所有到达某个阶段的线程的动态数量的等待方。

static final AtomicBoolean isTokenSync = new AtomicBoolean(false);
private static final Phaser phaser = new Phaser(1);

int phase = phaser.getPhase();
if (isTokenSync.compareAndSet(false, true)) {  

        generateAndSaveToken(...);

        phaser.arrive();
        isTokenSync.set(false);   
    }
    else {
        try {
            phaser.awaitAdvance(phase);
        } catch (InterruptedException e) {
        }
    }
}

Each time you arrive you will increment the phase count. 每次arrive您都会增加相位计数。 So let's say your start the method at phase == 1 the arrive will increment phase to 2 and all phases less than the current phase will advance. 因此,假设您在phase == 1开始该方法,到达将将阶段增加到2,并且所有阶段都将小于当前阶段。

It looks like you are looking for a Singleton . 看起来你正在寻找一个Singleton

See here for a good answer. 在这里看到一个很好的答案。

Something like this should work. 这样的事情应该有效。

public static class SingletonToken {

    private final String theToken;

    private SingletonToken() {
        // Do your generateAndSaveToken(...) here.
        theToken = "My token";
    }

    private static class SingletonHolder {

        // The constructor is in a static so will be called only once.
        private static final SingletonToken instance = new SingletonToken();
    }

    public static String getToken() {
        // By the time the code gets here the instance has been created.
        return SingletonHolder.instance.theToken;
    }
}

This essentially deferrs synchronisation to the class loader which is - by definition - thread safe. 这基本上是与类加载器的同步延迟, 根据定义 ,它是线程安全的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM