1

簡単な要件: - 1 日、1 時間、または 1 分ごとに 0 にリセットされる名前付きカウンター。制限を超えてインクリメントする次のリクエストは、インクリメントではなくリセットされます。タイマー・アラームの時刻合わせが不要です。- API はシンプルであるべき - スレッドセーフ

使用例です。制限のロギングまたはチェックに使用される特定のアプリケーション/ビジネス イベントのカウンターを保持します。特定のリソースが 1 日の制限を超えて使用されていないかどうかを確認し、そのリソースへのアクセスを停止します。

4

1 に答える 1

2

更新: 興味のある人のために GitHub に投稿された最新バージョン - https://github.com/mickyr/Awesome-Counter

これまでの私の最小限の実装。問題や改善点が見つかった場合は、批評してください。フィードバック、負または正を歓迎します。それは学習の機会になります:

リセット可能なカウンター クラス:

import java.util.concurrent.atomic.AtomicInteger;

public class ResettableCounter {
    private String policyString;
    private AtomicInteger count;

    public ResettableCounter(String name, AtomicInteger counter) {
        this.policyString = name;
        this.count = counter;
    }

    public String getPolicyString() {
        return policyString;
    }

    public void setPolicyString(String policyString) {
        this.policyString = policyString;
    }

    public AtomicInteger getCount() {
        return count;
    }

}

CounterPolicy列挙型

public enum CounterPolicy{
    YEARLY("yyyy"),
    MONTHLY("yyyy/MM"),
    DAILY("yyyy/MM/dd"),
    HOURLY("yyyy/MM/dd hh"),
    PERMINUTE("yyyy/MM/dd hh:mm");

    private String format;

    private CounterPolicy(String format) {
        this.format = format;
    }

    public String getFormat(){
        return this.format;
    }
}

ResettableCounter レジストリ クラス:

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import CounterPolicy;
import ResettableCounter;

public class ResetableCounterRegistry {
    private ConcurrentHashMap<String, ResettableCounter> counterRegistry = new ConcurrentHashMap<String, ResettableCounter>();
    private CounterPolicy policy = CounterPolicy.DAILY;

    public int incrementCount(String counterName){
        ResettableCounter counter = counterRegistry.get(counterName);       
        DateFormat dateFormat = new SimpleDateFormat(policy.getFormat());
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        if(counter==null)counterRegistry.putIfAbsent(counterName, new ResettableCounter(dateFormat.format(cal.getTime()), new AtomicInteger()));
        counter=counterRegistry.get(counterName);
        if(!dateFormat.format(cal.getTime()).equals(counter.getPolicyString())){
            int count = counter.getCount().get();
            if(counter.getCount().compareAndSet(count, 0))
                counter.setPolicyString(dateFormat.format(cal.getTime()));
            else counter.getCount().incrementAndGet();
        }
        else counter.getCount().incrementAndGet();
        return counter.getCount().get();
    }

    public void setPolicy(CounterPolicy policy) {
        this.policy = policy;
    }   
}

私が言ったように、これは最小限の実装ですが、うまくいけば、良い会話を呼び起こしたり、同様のユースケースを持つ誰かを助けることができます.

于 2013-03-07T16:35:10.927 に答える