java同步机制

时间:2011-04-15 16:24:00

标签: java synchronization

Web应用程序查询外部服务器。如果超过80%的服务器请求在过去'n'分钟内发送失败,则Web应用程序应退出查询服务器并执行其他逻辑。我可以想到一个原子整数被失败的请求递增。但我不认为原子整数支持在原子整数的值达到特定值时要执行的任何操作。在java中有没有更聪明的方法呢?

2 个答案:

答案 0 :(得分:1)

好吧,在更新你的原子整数后,你可以检查它的值,如果满足80%,那么你可以采取行动(比如将该服务器标记为'弱响应等)。如果您在多线程环境中工作,那么您的解决方案没有任何问题。

另一种解决方案是让线程调用synchronized方法来增加非原子整数并执行检查。该整数必须是此方法所属类的属性。

答案 1 :(得分:0)

如果您想要监控过去'N'分钟内的事件,您需要的不仅仅是整数。你需要知道'N'分钟前发生了什么,这样你才能保持你的成功水平估计正确。

这是一种方法:

import java.util.LinkedList;

/**
 * Class that monitors outcomes for until the proportion of successes in a
 * specified time window falls below a trigger level, at which point an action
 * is invoked.
 * 
 * @author Simon
 */
public class SuccessMonitor {
    /** An outcome */
    static class Outcome {
        /** Time of outcome */
        final long eventTime = System.currentTimeMillis();

        /** True for success, false for failure */
        boolean outcome;
    }

    /** The action to invoke when there are two few successes */
    private final Runnable action_;

    /** The history of outcomes in the time window */
    private final LinkedList<Outcome> events_ = new LinkedList<Outcome>();

    /** Number of successes in the time window */
    private int goodCount_ = 0;

    /** Synchronization lock */
    private final Object lock_ = new Object();

    /** Length of the time window in milliseconds */
    private final long trackTime_;

    /** The success proportion at which to invoke the action */
    private final double triggerLevel_;


    /**
     * New monitor
     * 
     * @param trackTime
     *            number of milliseconds to retain history for
     * @param triggerLevel
     *            the level at which to invoke the action
     * @param action
     *            the action
     */
    public SuccessMonitor(long trackTime, double triggerLevel, Runnable action) {
        trackTime_ = trackTime;
        triggerLevel_ = triggerLevel;
        action_ = action;
    }


    private void check(boolean result) {
        // create a new outcome
        Outcome out = new Outcome();
        out.outcome = result;

        double level;
        synchronized (lock_) {
            // add the new outcome
            goodCount_ += (result) ? 1 : 0;
            events_.addLast(out);

            // remove expired outcomes
            long expire = System.currentTimeMillis() - trackTime_;
            while( (!events_.isEmpty())
                    && (events_.getFirst().eventTime < expire) ) {
                out = events_.removeFirst();
                goodCount_ -= (out.outcome) ? 1 : 0;
            }

            // Calculate the success level.
            if (events_.isEmpty()) {
                // if empty assume ok
                level = 1.0;
            } else {
                // calculate success level
                level = (double) goodCount_ / events_.size();
            }
        }

        // if level has fallen too low, invoke action
        if (level < triggerLevel_) action_.run();
    }


    /**
     * Notify this monitor of a failure.
     */
    public void fail() {
        check(false);
    }


    /**
     * Reset this monitor, causing it to discard all currently stored history.
     */
    public void reset() {
        synchronized (lock_) {
            events_.clear();
            goodCount_ = 0;
        }
    }


    /**
     * Notify this monitor of a success.
     */
    public void success() {
        check(true);
    }
}