2009-08-14 14 views
7

Sto utilizzando GWT e Google App Engine. Ho una serie di record e voglio aggiornarli ogni 30 minuti. Nel ServiceImpl Ho il codice maggese:GWT, Google App Engine, TimerTask o Thread in ServiceImpl throw exception

new Timer().schedule(new TimerTask(){ 
    @Override 
    public void run() { 
     try { 
      Thread.sleep(30000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     result = updateFeeds(); 
    } 
}, 30000,Long.MAX_VALUE); 

Quando eseguo l'applicazione e quando ottengo:

com.google.gwt.user.server.rpc.UnexpectedException: 
Service method 'public abstract java.util.List org.joke.planet.client.FeedService.loadFeeds()' threw an unexpected exception: 
java.security.AccessControlException: access denied (java.lang.RuntimePermission modifyThreadGroup) 

alla prima linea o il codice incollato.

La mia domanda è COME posso fare un assistente in background che funzioni in GWT + servizio AppEngine?

risposta

3

Non è possibile utilizzare java.util.Timer perché crea un thread ordinario, che non è consentito su AppEngine. Tuttavia, è possibile utilizzare impianto di thread in background del AppEngine Moduli API, come documentato qui: https://developers.google.com/appengine/docs/java/modules/#Java_Background_threads

Si noti che è possibile utilizzare solo thread in background su istanze scala manualmente. In questo esempio, un thread in background stampa un messaggio ogni 30 secondi, per sempre:

Thread thread = ThreadManager.createBackgroundThread(new Runnable() { 
    public void run() { 
    try { 
     while (true) { 
     System.err.println("Doing something!"); 
     Thread.sleep(30_000); 
     } 
    } catch (InterruptedException ex) { 
    } 
    } 
}); 
thread.start(); 
-1

Il problema non è solo nel motore di app, ma in generale in qualsiasi contenitore di servlet. Quando si è in un metodo di servizio (che si trova sempre nel contenitore Servlet), non è possibile creare thread e dormire.

Nel mondo il servizio scalabile di oggi, Thread.sleep è una brutta cosa ....

+3

Questo è quasi completamente sbagliato. In un normale contenitore Servlet è perfettamente possibile/desiderabile creare thread di sfondo che eseguano azioni periodiche. Hai ragione nel dire che Thread.sleep è cattivo sul thread di richiesta, ma non su un thread in background. – Geoff

+0

Devo echo @Geoff, sostenendo che Thread e sleep() sono dannosi per la scalabilità è esattamente l'opposto della situazione. Il sonno ben posizionato è vitale per massimizzare la potenza della concorrenza. Se si esegue in ambiente a thread singolo, Thread.sleep() è una cattiva idea.Esegui da qualsiasi altra parte, ed è l'unico modo per abbandonare la CPU quando non ne hai bisogno e devi aspettare processi asincroni. – Ajax

3

Si signore, potrebbe beneficiare di classe ThreadManager urrà di AppEngine.

https://developers.google.com/appengine/docs/java/backends/overview#background_threads

Usa ThreadManager.currentRequestThreadFactory() per ottenere una fabbrica di filo che interromperà le discussioni generati non appena la richiesta corrente è finita, e ThreadManager.backgroundThreadFactory() per deporre le uova le discussioni che durerà fino a quando si per favore (ma funziona solo sui backend)

Per le richieste di frontend, si consiglia di tenere traccia dei thread e chiamare thread.join() se si desidera che finiscano prima che il filtro di richiesta appengine li interrompa.

+0

I backend sono stati deprecati a favore dei moduli; vedi https://developers.google.com/appengine/docs/java/modules/#Java_Background_threads. –