Bunların nasıl yapılabileceği bir örneği var mı? Yoksa çöp toplayıcı tarafından mı ele alınır? tomcat6 kullanarak im
Bunların nasıl yapılabileceği bir örneği var mı? Yoksa çöp toplayıcı tarafından mı ele alınır? tomcat6 kullanarak im
Javadoc şöyle diyor:
"Her iş parçacığı, iş parçacığı olduğu sürece ve ThreadLocal örneğine erişilebildiği sürece iş parçacığı yerel değişkeninin kopyasına örtük bir başvuruda bulunur. Bir iş parçacığı kaybolduğunda, iş parçacığı yerel örneklerinin tüm kopyaları çöp koleksiyonuna tabidir. (Bu kopyalara başka referanslar olmadıkça).
Uygulamanız veya (istek dizileri hakkında konuşuyorsanız) kapsayıcı, iş parçacığı ölmediği anlamına gelen bir iş parçacığı havuzu kullanır. Gerekirse, iş parçacığıyla kendiniz ilgilenmeniz gerekir. Bunu yapmanın tek temiz yolu aramaktır.
ThreadLocal.remove() yöntem.
Bir iş parçacığı havuzundaki iş parçacığı için iş parçacığı öğelerini temizlemek isteyebileceğiniz iki neden vardır:
İş parçacığı yerel bellek sızıntıları normalde sınırlı sayıda iş parçacığı havuzuyla ilgili önemli bir sorun olmamalıdır. yani iplik yeniden kullanıldığında. Ancak, yeni bir yaratma hatasını yaparsanız
ThreadLocal tekrar tekrar örnekleri (
static singleton örneğini tutmak için değişken), iş parçacığı yerel değerleri üzerine yazılmaz ve her iş parçacığında birikir
threadlocals harita. Bu ciddi bir sızıntıya neden olabilir.
Bir web sunucusunun bir HTTP isteğinin işlenmesi sırasında oluşturulan / kullanılan iş parçacığı hakkında konuştuğunuzu varsayarsak, iş parçacığı yerel sızıntılarını önlemenin bir yolu,
ServletRequestListener senin webapp ile
ServletContext ve dinleyiciyi uygulamak
requestDestroyed Geçerli iş parçacığı için iş parçacığı öğelerini temizleme yöntemi.
Bu bağlamda olasılığını da göz önünde bulundurmanız gerektiğini unutmayın. bilgi bir istekten diğerine sızmak.
Gerçek iş parçacığı yerel değişkenine bir başvuru olmadığında, geçerli iş parçacığındaki tüm iş parçacığı yerel değişkenlerini temizlemek için bazı kodlar. Ayrıca, diğer iş parçacıklarının yerel değişkenleri temizlemek için de genelleştirebilirsiniz:
private void cleanThreadLocals() { try { // Get a reference to the thread locals table of the current thread Thread thread = Thread.currentThread(); Field threadLocalsField = Thread.class.getDeclaredField("threadLocals"); threadLocalsField.setAccessible(true); Object threadLocalTable = threadLocalsField.get(thread); // Get a reference to the array holding the thread local variables inside the // ThreadLocalMap of the current thread Class threadLocalMapClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap"); Field tableField = threadLocalMapClass.getDeclaredField("table"); tableField.setAccessible(true); Object table = tableField.get(threadLocalTable); // The key to the ThreadLocalMap is a WeakReference object. The referent field of this object // is a reference to the actual ThreadLocal variable Field referentField = Reference.class.getDeclaredField("referent"); referentField.setAccessible(true); for (int i=0; i < Array.getLength(table); i++) { // Each entry in the table array of ThreadLocalMap is an Entry object // representing the thread local reference and its value Object entry = Array.get(table, i); if (entry != null) { // Get a reference to the thread local object and remove it from the table ThreadLocal threadLocal = (ThreadLocal)referentField.get(entry); threadLocal.remove(); } } } catch(Exception e) { // We will tolerate an exception here and just log it throw new IllegalStateException(e); } }
Temizleme yapmanın bir yolu yok
ThreadLocal içindeki değerler hariç onları ilk etapta yerleştiren iş parçacığı (veya iş parçacığı çöp toplandığında - iş parçacığı ile durum). Bu, bir servlet isteği tamamlandığında (veya AsyncContext'i Servlet 3'teki başka bir iş parçacığına aktarmadan önce) ThreadLocal öğelerinizi temizlemeye dikkat etmeniz gerektiği anlamına gelir, çünkü bu noktadan sonra o belirli çalışan iş parçacığına girme şansınız olmayacaktır. Sunucu yeniden başlatılmamışken web uygulamanızın yeniden dağıtılmadığı durumlarda belleği kaçıracak.
Böyle bir temizlik yapmak için iyi bir yer ServletRequestListener.requestDestroyed ().
Eğer yayı kullanırsanız, gerekli tüm kablo bağlantıları zaten mevcutsa, temizlik kapsamı hakkında endişelenmeksizin isteklerinizi kapsam içine alabilir (otomatik olarak gerçekleşir):
RequestContextHolder.getRequestAttributes().setAttribute("myAttr", myAttr, RequestAttributes.SCOPE_REQUEST); . . . RequestContextHolder.getRequestAttributes().getAttribute("myAttr", RequestAttributes.SCOPE_REQUEST);
Tekrar Javadoc belgelerini tekrar okumak:
'Her iş parçacığı, iş parçacığı canlı olduğu ve ThreadLocal örneğinin erişilebilir olduğu sürece iş parçacığı yerel değişkeninin kopyasına örtük bir başvuruda bulunur; Bir iş parçacığı ortadan kalktıktan sonra, iş parçacığı yerel örneklerinin tüm kopyaları çöp toplamaya tabidir (bu kopyalara başka referanslar olmadıkça). '
Bir şeyi temizlemeye gerek yok, hayatta kalmak için sızıntı için bir 'VE' koşulu var. Dolayısıyla, iş parçacığı uygulamanın uygulandığı bir web kapsayıcısında bile, webapp sınıfı kaldırıldığı sürece (üst sınıf yükleyicide yüklenen statik bir sınıfta yalnızca birleştirme başvurusu bunu engelleyecektir ve bunun ThreadLocal ile değil, statik verilerle paylaşılan kavanozlarla genel sorunları vardır) daha sonra AND'nin ikinci ayağı koşul artık karşılanmamaktadır, bu nedenle iş parçacığı yerel kopyası çöp toplama için uygundur.
Uygulama iş parçacığı belgelere uygun olduğu için iş parçacığı yerel bellek sızıntılarının nedeni olamaz.
Eski olmasına rağmen bu soruya verdiğim cevaplara katkıda bulunmak istiyorum. Ben aynı sorun (gson threadlocal isteği iş parçacığından kaldırılmıyor) tarafından sorulmuştu ve hatta bellek (her zaman büyük zaman berbat!) Bitti zaman sunucu yeniden başlatmayı rahatlattı.
Dev moduna ayarlanmış bir java web uygulaması bağlamında (sunucu, kodda bir değişiklik algıladığında ve muhtemelen hata ayıklama modunda çalışırken her seferinde geri dönecek şekilde ayarlanmıştır), threadlocals'ın harika olabileceğini çabucak öğrendim ve bazen bir acı olur. Her istek için bir threadlocal Invocation kullanıyordum. Çağrının İçinde. Bazen yanıtımı üretmek için gson kullanabilirim. Invocation'ı filtredeki bir 'try' bloğuna sardım ve onu 'nihayet' bloğun içinde yok edecektim.
Gözlemlediklerim (bunu şu ana kadar destekledim), birkaç dosyada değişiklik yaparsam ve sunucum sürekli değişimlerim arasında sıçrarsa, sabırsızlaşır ve sunucuyu yeniden başlatırdım (tomcat tam olarak) IDE'den. Muhtemelen, 'Bellek yetersiz' istisnası ile sonuçlanırdı.
Bu konuyla ilgili olarak benim app nasıl bir ServletRequestListener uygulama eklemek ve benim sorunum kayboldu. Sanırım, bir isteğin ortasında, sunucunun birkaç kez geri dönmesi halinde, threadlocals'ım temizlenemedi (gson dahil), bu yüzden threadlocals ile ilgili uyarı alırım ve iki veya üç uyarı daha sonra, Sunucu çökecektir. ServletResponseListener, threadlocals'ımı açık bir şekilde kapatırken, gson sorunu ortadan kalktı.
Umarım bu mantıklıdır ve size threadlocal sorunların üstesinden nasıl geleceğine dair bir fikir verir. Bunları her zaman kullanım noktaları etrafında kapatın. ServletRequestListener'de, her bir threadlocal sarıcıyı sınayın ve hala bazı nesnelere geçerli bir başvurusu varsa, o noktada yok edin.
Ayrıca, bir threadlocal'ı bir sınıfa statik bir değişken olarak sarmanın bir alışkanlık haline getirdiğine de dikkat etmeliyim. Bu şekilde ServeltRequestListener'da yok ederek, aynı sınıfın etrafına takılan diğer örneklerden endişelenmenize gerek kalmayacağı garanti edilebilir.
JVM, ThreadLocal nesnesinde bulunan tüm referanssız nesneleri otomatik olarak temizler.
Bu nesneleri temizlemenin bir başka yolu (örneğin, bu nesneler, etrafta bulunan tüm güvenli olmayan nesneler olabilir) onları temelde tutan bazı Nesne Tutucu sınıfının içine koymaktır ve nesneyi temizlemek için sonlandırma yöntemini geçersiz kılabilirsiniz bunun içinde yer alır. Yine Çöp Toplayıcısına ve onun politikalarına, ne zaman
finalize yöntem.
İşte bir kod örneği:
public class MyObjectHolder { private MyObject myObject; public MyObjectHolder(MyObject myObj) { myObject = myObj; } public MyObject getMyObject() { return myObject; } protected void finalize() throws Throwable { myObject.cleanItUp(); } } public class SomeOtherClass { static ThreadLocal<MyObjectHolder> threadLocal = new ThreadLocal<MyObjectHolder>(); . . . }