luca
luca

Reputation: 3318

Spring and synchronized method to guarantee a specific number of method executions simultaneously

I'm using Spring and I would like to know how session, class and methods works (how many instance of one class I have and why). In my case I have a Component class with an async method that calls another class with a ProcessBuilder inside:

@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");        
        }    
    }
}

This is my TaskExecutor configuration:

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

I would like to control the number of processes because otherwise server may go down. I was wondering how I can achive this, using synchronization? For example I should execute 10 processes, after that other request must wait that at least one process is ended. Maybe a stupid solution may be a static variable and an active wait with a while(i>10) this.sleep(10000)... Thanks

Upvotes: 2

Views: 1044

Answers (2)

Vladimir G.
Vladimir G.

Reputation: 418

I believe a Semaphore is exactly what you are after. If you need a maximum of 10 processes running at a time, try this raw snippet:

@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();
    }
}

UPDATE:

There might be a problem with this approach though. Considering that Semaphore.acquire() is blocking, if you are submitting hundreeds of this processes and these take a long time to complete, it is possible that all the threads in the ThreadPoolTaskExecutor will block waiting for a permit. I think it is important to keep that in mind.

Upvotes: 1

Mr_Thorynque
Mr_Thorynque

Reputation: 2002

You can configure the pool (ThreadPoolTaskExecutor) using by spring @Async

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

It'll garantee the max number of threads and inducting the number of process.

Upvotes: 1

Related Questions