2012-04-09 16 views
5

Nella registrazione dei dati Java, avvio il gestore su init() e chiudo il gestore su destroy() e funziona perfettamente: è stato creato un file di registro, ecc. Se l'utente aggiorna la pagina normalmente, crea comunque solo un file di registro.Applet Java: come assicurarsi che l'eliminazione sia terminata prima dell'aggiornamento della pagina

Tuttavia, se l'utente aggiorna la pagina con l'applet un paio di volte velocemente, sembra che destroy() non venga chiamato o che non abbia completato l'operazione e dal momento che init() viene richiamato di nuovo, presuppone che il file precedente sia ancora bloccato e crea un nuovo file di registro.

Ho provato a utilizzare sia destroy() che finalize() per chiudere il gestore ma non funziona. Qualcuno ha qualche idea su come risolvere questo problema?

Un'altra domanda minore è: cosa è successo in realtà se init() non è terminato e la pagina viene aggiornata. Continuerà il processo e alla fine non riuscirà a chiamare destroy() o si fermerà proprio lì?

+0

Potresti aggiungere al codice di domanda dei metodi "init" e "destroy"? Almeno parti relative al gestore di registri. –

risposta

4

Citazione di Java Tutorials:

Il software plug-in Java crea un thread di lavoro per ogni Java applet .

In ambiente multithreading è necessario prestare molta attenzione alle risorse condivise. L'approccio migliore e più semplice è quello di non condividere nulla (scale migliori e nessun deadlock possibile).

Suppongo che inizializzi il gestore ogni volta in "init" -method. Se è vero, è necessario utilizzare un logger condiviso statico (controllare questo link). Aiuterà a migliorare un po 'la situazione, ma se si avvia più di un browser con l'applet, verrà creato ancora un nuovo file di registro. E questa soluzione alternativa non è raccomandata da Oracle e conservata per compatibilità con le versioni precedenti.


Soluzione consigliata e facile da implementare: "ogni applet deve avere il proprio data logger e scrivere nel proprio file". Codice per il file di log generazione nome:

private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); 

private String generateFileName() { 
    return String.format("applets-log/%s-%s.log", dateFormat.format(new Date()), UUID.randomUUID()); 
} 

Inoltre, Best Practices For Applet Development.


risposta alla tua domanda minore (cambiato):

Secondo discussione di questo old bug nel plug-in Java, applet potrebbe essere interrotta in qualsiasi momento con un certo intervallo predefinito per la pulizia. Quindi dovresti inserire il codice di pulitura delle risorse nel tuo metodo "stop" o "distruggi", ma non dovresti fare affidamento su quale codice verrà eseguito.

applet del ciclo di vita è controllata dal browser e le applet non dovrebbe essere dato capacità di eseguire quando il suo documento di hosting è distrutto da browser.

Da 6u10, sia vecchi plug e nuovo plugin applicare arresto applet dopo un determinato periodo di tempo (1000 ms nel vecchio plug e 200ms a nuovo plugin) per applet di fermarsi.

+0

Ecco cosa stavo dicendo. –

0

Spero che non stiate testando in FF. Leggi qui: https://bugzilla.mozilla.org/show_bug.cgi?id=638070

+0

che non è il caso, in quanto l'applet funziona perfettamente normale, non importa quante volte si preme aggiornamento, l'applet funziona ancora. Semplicemente non uccide il file lck e causa la creazione di più file di registro – Harts

0

Si è semplicemente imbattuto in una limitazione fondamentale con ambienti multi-thread.

Non si sa davvero quando destroy() o finalize() verrà chiamato rispetto ad altri thread. Quando il browser ricarica la pagina, può caricare l'applet in una nuova discussione. Se l'utente esegue due volte il ricaricamento rapido, potrebbe creare 2 nuovi thread, chiamare il numero init() sul 2o (che l'utente vede effettivamente) prima di chiamare init() su quello che l'utente non vede mai e prima di chiamare destroy() sul precedente. All'altra estremità del ciclo di vita, finalize() viene chiamato dal thread Garbage Collection probabilmente molto lungo dopo che l'oggetto non è più necessario. Stai lavorando in un ambiente multi-thread e non puoi contare su alcun ordine di operazioni tra i thread.

Per citare il Javadoc:

Un applet è un piccolo programma che è destinato a non essere eseguito da solo, ma piuttosto per essere incorporato all'interno di un'altra applicazione.

È davvero l'applicazione esterna che dovrebbe controllare la creazione/apertura e chiusura del registro se si avrà un solo file di registro. Se l'applicazione esterna è un browser Web, non è possibile risolvere il problema riscontrato. Quindi, se si sta eseguendo l'applet in un browser Web, non si dovrebbero scrivere registri sul file system. Questo è solo un comportamento generalmente scortese.

Se è necessario disporre di file di registro per le applet all'interno di un browser Web, la soluzione più semplice è per ciascuna chiamata a init() per creare un nuovo file specifico per tale chiamata dell'applet. Se si desidera ottenere risultati ambiziosi, è possibile utilizzare i file di blocco per indicare quali file erano in uso e al momento destroy() concatenare i file di registro sbloccati in uno più grande, ma di nuovo si ha il problema di coordinare i processi di concatenazione tra thread.

+0

Hai torto su 'Se l'applicazione esterna è un browser web, non puoi risolvere il problema che stai riscontrando'. I framework di registrazione (JUL, log4j ed ecc.) Sono thread-safe da usare. Quindi il problema potrebbe essere risolto utilizzando il logger condiviso statico che verrà utilizzato da tutte le istanze dell'applet. –

+0

@Vadim non è possibile garantire che il browser richiamerà il proprio inizializzatore statico solo una volta. Il browser è libero di creare un nuovo caricatore di classi di applet e di ricaricare l'applet ad ogni aggiornamento, richiamando in tal modo gli inizializzatori statici ogni volta. Anche se in pratica non lo fa, non si dovrebbe fare affidamento su inizializzatori statici chiamati solo una volta come modo per sincronizzare le istanze di applet. Cosa succede se, ad esempio, hai caricato la stessa applet nello stesso computer contemporaneamente in due diversi browser, ad esempio Firefox e Chrome? –

+0

Variabile statica inizializzata da JVM, al momento del caricamento della classe. Non mi aspetto problemi con il classloader in questa domanda SO, quindi passo alla discussione di JVM. Se l'utente avvia 2 diversi browser, ciascun browser avvia la propria JVM.Anche la nuova JVM potrebbe essere avviata se l'applet richiede specifici parametri JRE o JRE specifici (questa condizione è OK per la domanda corrente, poiché discutiamo di un'applet, quindi i requisiti e i parametri di JRE saranno gli stessi). Quindi, la variabile statica condivisa funzionerà nel caso di un browser e il problema dalla domanda apparirà nel caso di diversi browser. –