【问题标题】:Spring and synchronized method to guarantee a specific number of method executions simultaneouslySpring 和同步方法,以保证同时执行特定数量的方法
【发布时间】:2016-10-10 09:45:46
【问题描述】:

我正在使用 Spring,我想知道会话、类和方法是如何工作的(我拥有一个类的多少个实例以及为什么)。 在我的例子中,我有一个带有 async 方法的 Component 类,该方法调用另一个内部带有 ProcessBuilder 的类:

@Component
@PropertySource(value = { "classpath:application.properties" })
public class ZipAndMat {
.....
......
    @Async
    public void createZipAndMat(User currentUser, String originalFileName){
        conversion(path, name, timeSample, timeout):
    }

    private void conversion(String path, String name, String timeSample, String timeout) throws Exception {        
        ProcessBuilder pb = new ProcessBuilder("java", "-XX:-UseParallelGC", "-Xss512k", "-jar", env.getRequiredProperty(PROPERTY_NAME_CONVERSION_PATH), path, name, timeSample, timeout);        
        pb.inheritIO();        
        Process p = pb.start();        
        int error = p.waitFor();           
        if (error !=0) {            
            if (p.isAlive()) {                
                p.destroyForcibly();           
            }                        
            throw new MCRException("Error with conversion");        
        }    
    }
}

这是我的 TaskExecutor 配置:

@Override
public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(10);
    executor.setMaxPoolSize(100);
    executor.setQueueCapacity(100);
    executor.initialize();
    return executor;
}

我想控制进程数,否则服务器可能会宕机。我想知道如何使用同步来实现这一点?例如,我应该执行 10 个进程,之后其他请求必须等待至少一个进程结束。也许一个愚蠢的解决方案可能是一个静态变量和一个while(i>10) this.sleep(10000)...的主动等待 谢谢

【问题讨论】:

  • 你不能通过同步来实现它,但是你可以使用来自java.util.concurrent的计数信号量。
  • 只需配置适当的TaskExecutor 并为其提供您希望能够执行的最大并发任务数。而不是自己动手。
  • @EJP 信号量似乎很有趣,我正在阅读文档。
  • @M.Deinum TaskExecutor,如果我理解正确的话,它对我的​​应用程序中的并发任务很有用,而不是对特定方法有用。我想了解有关 Spring 如何处理用户会话和 TaskExecutor 参数的更多详细信息

标签: java spring multithreading jakarta-ee process


【解决方案1】:

您可以使用spring @Async 配置池(ThreadPoolTask​​Executor)

https://spring.io/guides/gs/async-method/

保证最大线程数和引入进程数。

【讨论】:

  • 但是例如,一个线程可能会抛出更多的进程调用转换方法多次?我怎样才能拥有最多十个进程(所以执行中的十个转换方​​法)以及弱点是什么(当 Spring 达到最大进程数时会发生什么)。谢谢
  • 在你的线程代码中启动一个进程,这样它就可以工作了。如果 spring 使用所有池大小,您可以配置一个队列大小来处理调用。
【解决方案2】:

我相信Semaphore 正是您所追求的。如果您一次最多需要运行 10 个进程,请尝试以下原始 sn-p:

@Component
@PropertySource(value = { "classpath:application.properties" })
public class ZipAndMat {

    private final Semaphore processes = new Semaphore(10);

    @Async
    public void createZipAndMat(User currentUser, String originalFileName){
        processes.acquire();
        conversion(path, name, timeSample, timeout);
        processes.release();
    }
}

更新:

不过,这种方法可能存在问题。考虑到 Semaphore.acquire() 是阻塞的,如果你正在提交数百个这样的进程并且这些进程需要很长时间才能完成,那么 ThreadPoolTask​​Executor 中的所有线程可能会阻塞等待许可。我认为记住这一点很重要。

【讨论】:

  • 谢谢,信号量不应该是静态的吗?在这个过程中我有一个计时器,它到期后我终止了这个过程。
  • 好问题。假设您的 bean 范围是单例的,您不必将 Semaphore 实例设为静态,因为您将只有一个该 bean 的实例。如果您的 bean 的范围是原型,您可能希望将其设为静态。
  • 单例作用域是 Spring 中的默认作用域,所以我认为这已经足够了,但为了安全起见,我什至可以将 Semaphore 实例设为静态。谢谢,我试试
猜你喜欢
  • 1970-01-01
  • 2021-10-19
  • 2015-12-10
  • 2014-04-18
  • 2011-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多