2012-10-01 56 views
10

Tengo la aplicación MVC de primavera en funcionamiento y lo que intento hacer a continuación es iniciar o enviar una tarea en segundo plano desde mi aplicación.Enviar una tarea en segundo plano desde la aplicación mvc de primavera

Básicamente me gustaría mantener la tarea hasta que se complete incluso si el usuario decide hacer algo más en la aplicación.

Pero también me gustaría detener/matar/pausar la tarea si fuera necesario. Como no he hecho esto antes, estoy buscando una buena/mejor forma de hacerlo.

He encontrado estos sean útiles:

http://blog.springsource.com/2010/01/05/task-scheduling-simplifications-in-spring-3-0/

How do you kill a thread in Java?

Java threads: Is it possible view/pause/kill a particular thread from a different java program running on the same JVM?

así que quería utilizar @Async tarea de presentar mi tarea en segundo plano, pero querían usar hilos id para obtenerlo más adelante y detenerlo si es necesario?

¿Es este el enfoque correcto? No tengo ninguna experiencia con multihilo, así que estoy aquí para escuchar. actualización

Código:

public interface Worker { 
    public void work(); 
    public void cancel(); 
} 

aplicación:

@Component("asyncWorker") 
public class AsyncWorker implements Worker { 

    @Async 
    public void work() { 
     String threadName = Thread.currentThread().getName(); 
     System.out.println(" " + threadName + " beginning work"); 
     try { 
       Thread.sleep(10000); // simulates work 
     } catch (InterruptedException e) { 
      System.out.println("I stopped"); 
     } 
     System.out.println(" " + threadName + " completed work"); 
    } 

    public void cancel() { Thread.currentThread().interrupt(); } 
} 

controlador para propósitos de prueba:

@ResponseBody 
@RequestMapping("/job/start") 
public String start() { 
    asyncWorker.work(); 
    return "start"; 
} 

@ResponseBody 
@RequestMapping("/job/stop") 
public String stop() { 
    asyncWorker.cancel(); 
    return "stop"; 
} 

Cuando visito /job/start, no puedo ejecutar más de una tarea al mismo tiempo. El otro comienza a ejecutarse solo después de que el primero haya completado

También cuando visito /job/stop el proceso no se detiene, ¿qué es lo que me falta aquí?

Respuesta

9

El uso de ID de hilo es demasiado bajo y frágil. Si decidió usar @Async annotation (buena opción) puede usar Future<T> para controlar la ejecución de la tarea. Básicamente el método debe devolver un Future<T> en lugar de void:

@Async 
public Future<Work> work() //... 

Ahora puede cancel() que Future o esperar a que se complete:

@ResponseBody 
@RequestMapping("/job/start") 
public String start() { 
    Future<Work> future = asyncWorker.work(); 
    //store future somewhere 
    return "start"; 
} 

@ResponseBody 
@RequestMapping("/job/stop") 
public String stop() { 
    future.cancel(); 
    return "stop"; 
} 

La parte difícil es almacenar el future objeto devuelto de alguna manera está disponible para solicitudes posteriores. Por supuesto, no puede usar un campo o ThreadLocal. Puede poner en sesión, tenga en cuenta que Future no es serializable y no funcionará en clusters.

Dado que @Async normalmente está respaldado por grupo de subprocesos, es probable que sus tareas ni siquiera se hayan iniciado. La cancelación simplemente lo eliminará del grupo. Si la tarea ya se está ejecutando, puede marcar isInterrupted() o manejar InterruptedException para descubrir la llamada cancel().

+0

+1 para @Async. Puede agregar un enlace a http: // static.springsource.org/spring/docs/3.0.x/reference/scheduling.html? –

+0

@Tomasz Nurkiewicz hola gracias por la respuesta. La clase que realmente contiene la implementación de 'fooAsync()' ¿necesita implementar Runnable? si tuviera que crear un método de cancelación que interrumpa el hilo realizando una tarea en segundo plano, ¿interrumpirá Thread.currentThread() .interrumpir ese hilo en particular? ¿Puedes dar un ejemplo, por favor? –

+0

@DavidGrant: seguro, también eres libre de editar cualquier publicación en SO (que ya hiciste, gracias). –

Cuestiones relacionadas