繁体   English   中英

Jira:线程安全小工具数据?

[英]Jira: Thread-safe Gadget Data?

我有一些数据(两个HashSet和一个Instantstamp时间戳),我希望将所有对JIRA(OpenSocial?)小工具/插件的请求共享-因为生成时间很长(几分钟),并且共享将有助于提高请求的执行效率。

偶尔(很少),请求可能包含一个参数,该参数指示应刷新此共享数据。 当然,第一次需要它时,它就会被填充。 数据代表过时的答案是可以的-它基于缓慢变化的事物并用于可视化趋势,因此可以容忍一次错误。

我想象当JIRA启动(或上传我的附加组件的新版本)并且在前几分钟出现多个请求时,我需要以线程安全的方式处理这些昂贵的共享数据。 目前,结果看起来不错,但据我了解,这只是偶然的缘故。

只有一个线程需要完成填充工作。 在启动时,其他线程当然必须等待,因为它们不能空手而退。 (如果所有线程都执行昂贵的初始化,则服务器上的不必要的负载很多)

但是在初始成本之后,如果有多个并发请求进入,并且其中一个请求包含“ refresh”参数,则只有一个线程需要为此付出代价-我同意其他线程使用昂贵数据的旧副本的情况从而保持性能,并在响应中包括“是的, 有人正在刷新数据,但这是使用旧副本的结果”。

有关数据的更多信息:两个HashSet和时间戳旨在表示时间上一致的快照。 HashSet的内容仅取决于数据库中的值,并且时间戳只是最近刷新的时间。 这些数据都不依赖于任何较早的快照。 而且它们都不依赖于程序状态。 时间戳仅用于粗略地回答“此数据的年龄”问题。 每次刷新数据时,我都希望时间戳记是较新的,但是如果错误的话,一切都不会中断。 它仅用于调试和透明。 由于快照不依赖于较早的快照或程序状态,因此可以将其包装并标记为易失性。

是否有最佳方法的明显选择? 替代方案的利弊?

您将需要使用Locks来同步对代码部分的访问,而您只需要一次执行一个线程即可。 SO和Oracle Java文档中有大量资源可以更详细地显示如何使用锁,但是类似的方法应该可以解决问题。

这个想法是,您想维护最近生成的一组结果的副本,并且始终返回该副本,直到拥有一组新的可用数据为止。

import java.util.concurrent.locks.ReentrantLock;

public class MyClass
{
    private volatile MyObject completedResults;
    private final ReentrantLock resultsLock;
    private final ReentrantLock refreshLock;

    public MyClass()
    {
        // This must be a singleton class (such as a servlet) for this to work, since every
        // thread needs to be accessing the same lock.

        resultsLock = new ReentrantLock();
        refreshLock = new ReentrantLock();
    }

    public MyObject myMethodToRequestResults(boolean refresh)
    {
        MyObject resultsToReturn;

        // Serialize access to get the most-recently completed set of results; if none exists,
        // we need to generate it and all requesting threads need to wait.

        resultsLock.lock();

        try
        {
            if (completedResults == null)
            {
                completedResults = generateResults();
                refresh = false; // we just generated it, so no point in redoing it below
            }

            resultsToReturn = completedResults;
        }
        finally
        {
            resultsLock.unlock();
        }

        if (refresh)
        {
            // If someone else is regenerating, we just return the old data and tell the caller that.

            if (!refreshLock.tryLock())
            {
                // create a copy of the results to return, since we're about to modify it on the next line
                // and we don't want to change the (shared) original!

                resultsToReturn = new MyObject(resultsToReturn);  
                resultsToReturn.setSomeoneElseIsRegeneratingTheStuffRightNow(true);
            }
            else
            {
                try
                {
                    completedResults = generateResults();
                    resultsToReturn = completedResults;
                }
                finally
                {
                    refreshLock.unlock();
                }
            }
        }

        return resultsToReturn;
    }
}

暂无
暂无

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

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