2016-10-10 3 views
2

Ich benutze Spring und ich möchte wissen, wie Sitzung, Klasse und Methoden funktionieren (wie viele Instanzen einer Klasse habe ich und warum). In meinem Fall habe ich eine Component Klasse mit einem async Methode, die eine andere Klasse mit einem ProcessBuilder innen ruft:Spring und synchronisierte Methode, um eine bestimmte Anzahl von Methodenausführungen gleichzeitig zu garantieren

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

Diese Konfiguration mein TaskExecutor ist:

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

Ich möchte die Anzahl der steuern Prozesse, weil sonst der Server untergehen kann. Ich habe mich gefragt, wie ich das erreichen kann, indem ich Synchronisation verwende? Zum Beispiel sollte ich 10 Prozesse ausführen, danach muss andere Anfrage warten, dass mindestens ein Prozess beendet ist. Vielleicht kann eine dumme Lösung eine statische Variable und eine aktive Wartezeit mit einem while(i>10) this.sleep(10000)... Dank sein

+1

Sie können es nicht mit Synchronisation erreichen, aber Sie können mit einem Zähl-Semaphor von 'java.util.concurrent'. – EJP

+0

Konfigurieren Sie einfach den entsprechenden 'TaskExecutor' und geben Sie ihm eine maximale Anzahl gleichzeitiger Aufgaben, die Sie ausführen möchten. Anstatt zu versuchen, es selbst zu tun. –

+0

@EJP Semaphore scheint sehr interessant, ich lese Dokumentation. – luca

Antwort

1

Sie den Pool konfigurieren können (ThreadPoolTaskExecutor) durch Feder mit @Async

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

Es wird die max garantee Anzahl der Gewinde und Induktion der Anzahl der Prozesse.

+0

arbeitet, aber zum Beispiel, kann ein Thread mehr Prozesse werfen, die Conversion-Methode mehrmals aufrufen? Wie kann ich maximal zehn Prozesse haben (also zehn Konvertierungsmethoden in Ausführung) und was ist die Schwachstelle (was passiert, wenn Spring die maximale Anzahl von Prozessen erreicht). Danke – luca

+0

In Ihrem Code auf Thread starten einen Prozess, so dass es funktioniert. Wenn Spring die gesamte Poolgröße verwendet, können Sie eine Warteschlangengröße konfigurieren, die die Anrufe behandelt. –

1

Ich glaube, ein Semaphore ist genau das, wonach Sie suchen. Wenn Sie maximal 10 Prozesse müssen zu einem Zeitpunkt ausgeführt wird, versuchen Sie diesen rohen Schnipsel:

@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:

Es könnte allerdings ein Problem bei diesem Ansatz. Wenn Sie bedenken, dass Semaphore.acquire() blockiert, wenn Sie Hunderte dieser Prozesse einreichen und diese eine lange Zeit benötigen, ist es möglich, dass alle Threads im ThreadPoolTaskExecutor das Warten auf eine Genehmigung blockieren. Ich denke, dass es wichtig ist, das im Hinterkopf zu behalten.

+0

danke, sollte der semaphor nicht statisch sein? In dem Prozess habe ich einen Timer und nachdem er abgelaufen ist, töte ich den Prozess. – luca

+0

Gute Frage. Sobald Ihr Bean-Bereich Singleton ist, müssen Sie die Semaphore-Instanz nicht statisch machen, da Sie nur eine Instanz dieser Bean haben. Wenn der Umfang Ihrer Bean ein Prototyp ist, möchten Sie sie möglicherweise statisch machen. –

+0

Der Singleton-Bereich ist der Standard-Bereich im Frühjahr, also denke ich, es ist genug, aber um sicher zu sein, könnte ich sogar die Semaphore-Instanz statisch machen. Danke, ich werde es versuchen – luca

Verwandte Themen