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

标签 java multithreading jira jira-plugin

我有一些数据(两个哈希集和一个即时时间戳),我希望对我的 JIRA(OpenSocial?)小工具/插件的所有请求进行共享 - 因为生成它需要很长时间(几分钟)并且因为共享将有助于提高请求的性能。

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

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

只有一个线程需要完成填充工作。启动时,其他线程当然必须等待,因为它们不能空手跳过。 (如果所有线程都执行昂贵的初始化,则会给服务器带来大量不必要的负载)

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

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

是否有一个明显的选择来解决这个问题的最佳方法?替代方案的优点和缺点?

最佳答案

您将需要使用锁来同步对代码中只需要一个线程同时执行的部分的访问。 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;
    }
}

关于java - Jira:线程安全的小工具数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24194267/

相关文章:

java - fork /加入 : optimal threads count

c# - 创建表单并在后台线程上使用 Form.ShowDialog

jira - 如何对多个组件的问题进行JQL查询

java - 安卓 ListView : how to change background color of specific cells (by index)?

java - 读取 Excel 的内容并使用我的 Robotium 测试用例中的值

java - 在 Java 中从数组创建对象数组

java - 如何从 Java 执行 Java?

c++ - 对 Boost 线程的 undefined reference

python jira 无法转换问题

c# - 如何通过 rest api 更新问题状态?