Domanda

Sono l'attuazione di un "manager" nella mia web app che può essere chiamato per impostare e ottenere quale contesto il sito web del thread corrente è in (abbiamo etichetta bianca il nostro sito in modo che il contesto sito web rappresenta quale sito siamo in )

Sto cercando di capire cosa la strategia migliore per fare questo, attualmente sto implementando le vendite di thread per WebSiteContexts in una mappa di hash concomitante:

private final ConcurrentHashMap<Thread, WebSiteContext> chm = new ConcurrentHashMap<Thread, WebSiteContext>();

all'inizio della filettatura (tramite un filtro servlet o attraverso impostazione manualmente) il filo viene associato alla sua WebSiteContext,

ma si vuole ripulire il Map per evitare una perdita di memoria. Quindi credo che una strategia è quella di scorrere le chiavi della discussione della mappa per scoprire se i fili sono "vivi" (thread.isAlive ()) e se non rimuoverlo per esempio come questo:

 public class Cleaner implements Runnable {
      private static final int INTERVAL = 6 * 1000; // 6 seconds
      public Cleaner() {
      }
      public void run() {
            // soo every interval iterate through the threads if they're dead then remove it from the map.
            while(true) {
               try {
                     Set<Thread> threads = chm.keySet();
                     Set<Thread> staleThreads = new HashSet<Thread>();
                     for (Thread tmpThread : threads) {

                        // if we get to a dead thread then clean the fucker up
                        if (!tmpThread.isAlive()) {
                           // think that we're going to get a run condition anyway
                           chm.remove(tmpThread);
                        }
                     }
                  Thread.sleep(INTERVAL);
               } catch (Exception e) {
                  log.error("caught exception e:", e);
               }
            }
      }
   }

, ma questo immagino che mi obbliga a sincronizzare l'accesso alla mappa (o lo fa?), Che è qualcosa che voglio evitare.

C'è qualche motivo "idiomatica" per la memorizzazione di attributi in discussioni in java o addirittura ripulire le mappe che hanno gli oggetti della discussione come chiavi? Sono aperto a utilizzare WeakReference / SoftReferences o addirittura se c'è qualche equivalente di Thread.getCurrentThread (). SetAttribute (Object, Object), che sarebbe grande

Saluti Simon B

È stato utile?

Soluzione

Il tuo approccio può funzionare, ma si finirebbe per fare più lavoro di quanto neeeded. ThreadLocal è quello che stai cercando. Questo vi permetterà di memorizzare gli oggetti legati alla ogni thread nell'applicazione. Il modo tipico di usarlo è quello di implementare il metodo initialValue () che assegna il primo valore. Esempio:

 private static final ThreadLocal<String> localAttribute = new ThreadLocal<String> () {
         protected Integer initialValue() {
             return "InitialValue";
     }
 };

Questo vi darà un nuovo thread locale con il valore iniziale di "InitialValue" quando si chiama prima localAttribute.get (). È quindi possibile chiamare localAttribute.set () per assegnare un valore diverso. Ogni thread richiedente avrà valori diversi per lo stesso attributo.

La cosa bella sull'utilizzo ThreadLocal è che quando il filo muore, il filo locale dovrebbe consentire i dati siano disponibili per la raccolta dei rifiuti.

Altri suggerimenti

Hai pensato a ThreadLocal?

Si sta definendo un "filo locale" spazio variabile per la durata di un richiamo servlet. Il modo migliore è quello di rimuovere il mapping allo stesso livello, come si è aggiunto, quindi se si aggiunge alla mappa in un ServletFilter vorrei aggiungere un blocco finally che ha rimosso la mappatura sulla via d'uscita. Lo stesso vale per un'aggiunta "manuale" in un servlet.

Alternative stanno avendo queste informazioni nel vostro ServletContext o aggiungendolo come attributo ThreadLocal.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top