2012-10-01 18 views
10

Çalışma yayımı MVC uygulamasına sahibim ve şimdi yapmaya çalıştığım şey, uygulamadan bir arka plan görevi başlatmak veya göndermek.Spring mvc uygulamasından bir arka plan görevi gönderme

Kullanıcı uygulamada başka bir şey yapmaya karar verse bile, görev tamamlanana kadar görevi sürdürmek isterim.

Ayrıca, gerekiyorsa görevi durdurmak/durdurmak/duraklatmak isterim. Bunu daha önce yapmadığımdan, bunu yapmak için iyi/daha iyi bir yol arıyorum.

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?

Yani benim arka plan görevi göndermek için @Async görevi kullanmak istedi, ancak konuları kullanmak istedi:

Bunları yararlı olduğu bulundu Daha sonra elde etmek ve gerekiyorsa durdurmak için id?

Bu doğru yaklaşım mı? Multithreading ile ilgili herhangi bir deneyimim yok, bu yüzden dinlemeye geldim.

Kod güncelleme:

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

uygulanması: test amaçlı

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

Denetleyici: Ben /job/start ziyaret ettiğinizde

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

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

, daha Şunu yürütemediğinden görev aynı anda. Diğeri yalnızca birincisi tamamlandıktan sonra yürütmeye başlar

Ayrıca /job/stop adresini ziyaret ettiğimde süreç durmuyor, burada ne eksik?

cevap

9

İplik tanıtımı çok düşük düzeydedir ve kırılgandır. @Async annotation (iyi seçim) kullanmaya karar verdiyseniz, görev yürütmeyi denetlemek için Future<T> kullanabilirsiniz.

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

zor kısmı bu yüzden her nasılsa döndü future nesneyi saklamaktır: Artık

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

işlemin tamamlanmasını sen Future olduğunu cancel() veya bekleyebilir: Temelde yöntemi Future<T> yerine void bir dönmelidir sonraki istekler için kullanılabilir. Tabii ki bir alanı kullanamazsınız veya ThreadLocal. Oturum açabilirsiniz, ancak Future'un seri hale getirilemeyeceğini ve kümeler arasında çalışmayacağını unutmayın.

Genellikle, @Async genellikle iş parçacığı havuzu tarafından desteklenir, sizin görevlerinizin başlamadı bile. İptal etmek sadece onu havuzdan kaldıracaktır. Görev zaten çalışıyorsa, iş parçacığı bayrağını işaretleyebilir veya cancel() aramasını bulmak için InterruptedException kodunu kullanabilirsiniz. @ Async için

+0

+1. Http: // statik için bir bağlantı ekleyebilir misiniz.springsource.org/spring/docs/3.0.x/reference/scheduling.html? –

+0

@Tomasz Nurkiewicz merhaba cevap için teşekkür ederim. Aslında fooAsync() 'nin uygulanmasını içeren sınıf, Runnable'ı uygulamak zorunda mı? Eğer thread arka plan görevini kesen bir iptal yöntemi oluştursaydım, Thread.currentThread(). Bir örnek verebilir misiniz lütfen? –

+0

@DavidGrant: elbette, SO üzerinde herhangi bir gönderiyi düzenlemekte de özgürsünüz (zaten yaptınız, teşekkürler). –