当前位置: 首页 > 知识库问答 >
问题:

如何避免并发执行一个耗时的任务而不阻塞?

申屠飞
2023-03-14
private static boolean running = false;

public void launchExpensiveTask() {
    if (running) return; // Do nothing

    running = true;
    try {
        runExpensiveTask();
    } finally {
        running = false;
    }
}
private static boolean running = false;
private static Object execLock = new Object();

public void launchExpensiveTask() {
    if (running) return; // Do nothing

    synchronized (execLock) {
        if (running) return;

        running = true;
        try {
            runExpensiveTask();
        } finally {
            running = false;
        }
    }
}

但后来我意识到,无论如何,我将以一个内部同步块结束,该块仍然可以在监视器入口以正确的定时保存一个线程,直到原始执行器离开临界部分(我知道这种可能性通常很小,但在这种情况下,我们考虑的是几个线程争夺这种长时间运行的资源)。

那么,你能用更好的方法思考吗?

Edit:我之前省略了部分上下文,为了正确起见,我需要在执行期间维护一个锁,以保存试图更改某些内部共享状态的其他方法。公平地说,到目前为止,我否决了有用的答案,包括两种情况:在启动任务后需要锁和不需要锁。

共有1个答案

叶坚
2023-03-14

我觉得这样更有道理:

 static volatile Boolean running = false;

    public static void launchTask()
    {
        synchronized(running)
        {
            if(running) return;
            running = true;
        }
            //DOSTUFF
            running = false;
    }

因为您实际上只需要在设置布尔值时进行同步:如果几个线程同时请求,第一个线程将设置running为true,其余的线程都将返回

但是,您的设计可能会有一个更好的整体模式。如果线程将请求提交到队列(ExecutorService?)得到Future或ListenableFuture(从番石榴)对象,然后继续做其他事情,直到Future完成计算?

 类似资料:
  • 我正在使用 Kubernetes 作为容器编排器构建一个微服务应用程序。该应用程序现已启动并运行,但我有其他问题。那是在我的服务中,我每天都有一个计划任务运行,当服务部署时,将运行多个服务实例(通过设置副本编号),创建多个同时运行的任务。我期望的是只有一个服务任务实例将运行,而不是多个实例。有什么技术可以处理这种情况吗? 库伯内特斯 Asp.net核心构建微服务 CI/CD的基岩实现 Fabrik

  • 我在<code>java.text.RuleBasedCollator中遇到线程阻塞问题。getCollationKey()当我的服务器负载过重时。 下面是出现问题的类: 下面是来自线程转储的一个片段,显示了有问题的阻塞: " xxxhttp 227 " prio = 5 tid = 0x 355 NID = 0x 163 BLOCKED归hybrishttp 109 Id = 236-stats

  • 我通过执行一些可调用项。如果线程列表只包含1个可调用的线程,那么我直接调用我的的方法。若列表包含超过1个可调用项,那个么我将通过线程池执行器并行执行所有这些线程。 我如何在Java8 CompletableFuture中实现这一点?如果增强了以避免阻塞,这将是一个加号。

  • 我正在从事一个spring boot项目,以自动化与gradle的集成测试。我最近开始在一家新企业工作,我的同事们按如下方式运行集成测试:在构建中。gradle文件有一个集成测试任务 启动任务后,应用程序开始在指定端口运行,然后打开postman,导入集合并运行测试。 我的工作是找到一种方法来跳过额外的点击,即自动运行邮递员集合。第一个想法是使用postman-run gradle插件,但由于企业

  • 问题内容: 我一直在开发Android应用程序,我每小时需要执行1个任务。我使用以下代码: 它对我有用,但是我的客户告诉我该任务只能工作1次,而不能工作1个小时。我在哪里弄错了?请告诉我。谢谢。 问题答案: 根据您的代码,ALARM_PERIOD为1000L,作为重复间隔。因此,我怀疑警报会在每1000毫秒内触发一次。 如果您设置每小时的重复间隔,则应为3600000L。并请注意,如果电话重新启动

  • 在Spark中,一次并行执行多少个任务?在Spark中如何将阶段划分为任务?DAG在RDD中是如何工作的? 但我没有找到明确的结论。 null null 如果这是真的,那么Spark在一个执行器中的行为不是有点不确定吗(单线程v.s.多线程)? 注意,从驱动程序运到执行程序的代码可能没有考虑使用synchronized关键字的自动性问题。 Spark对此是如何处理的?

  • 问题内容: 我有以下使用类的课程。所以我想做的是,在运行cp1实例处理方法的同时,我要并行运行。 但是,我要按顺序cp1,所以我要它运行并完成,如果cp2没有完成或失败,那就很好。如果确实失败,我想加入结果。该示例中未返回任何内容,但我想返回结果。 为此,应该使用TaskExecutor吗?还是线程? 我只希望cp2与cp1并行运行。或者,如果我添加更多内容,例如说cp3,我希望它也可以与cp1并

  • 我已经在Jenkins安装上配置了两个多分支项目(来自GitHub)。目前遗嘱执行人的数量是四个。 有时,当有很多分支要构建时,它最终会出现所有执行器都在等待免费执行器而什么都没有发生的情况。 你通常如何避免这种情况?当然,人们不能在一台机器上配置一百万个执行器来确保这种情况永远不会发生。 我现在有四个执行者试图构建,他们都在等待对方: 另一个问题是,这是如何/为什么可能的?他们没有实施任何机制来