2010-08-17 10 views
6

natywną widziałem jak to skomentowaćjava.lang.OutOfMemoryError: nie można utworzyć nowy wątek

one place i have seen this problem is if you keep creating threads, and instead of calling start(), call run() directly on the thread object. This will result in the thread object not getting dereferenced... So after sometime the message unable to create new native thread comes up

na Sun Java Forums

w mojej aplikacji, initialy planujemy używać nici, ale później zdecydowaliśmy już nie trzeba, więc po prostu wywołujemy run() zamiast start(). Czy potrzebujemy instrukcji GC dla nowej threadClass (..)?

mój startup kocur ustawienie

-Xms1024m -Xmx1024m -XX:MaxPermSize=450m 
+3

Ale jeśli wyłączysz metodę run() zamiast start(), JVM nie utworzy nowego wątku. Czyż nie? – sourcerebels

+0

uzgodnione. więc nawet jeśli używam nowej threadClass (..) w mojej metodzie warstwy usługi, nie ma potrzeby ręcznego czyszczenia? – cometta

+0

Dlaczego musisz tworzyć wątki wewnątrz Tomcat (serwer WWW)? Nie jest to zalecane. Spróbuj znaleźć alternatywne rozwiązanie: 1) oddzielny samodzielny proces z wątkami komunikującymi się przez RMI, JMS lub bazę danych; 2) może używając MessageDrivenBeans i JMS wewnątrz twojej aplikacji internetowej, jeśli jesteś w porządku z przejściem na serwer aplikacji J2EE, taki jak JBoss, Glassfish lub Geronimo; 3) inne ... :) – helios

Odpowiedz

11

Dlaczego tworzysz Thread w pierwszej kolejności?

Twój kod powinien zaimplementować interfejs Runnable.

Potem, gdy uznasz, że chcesz go uruchomić w wątku, prosty instancji Thread z Runnable jako argumentu i nazywają start() na obiekcie Thread.

Jeśli zamiast tego chcesz go uruchomić w bieżącym wątku, po prostu zadzwoń pod numer run() na swoim obiekcie Runnable.

Ma to kilka zalet:

  • nie pociąga za sobą żadnych Thread obiektów dopóki nie dbają o oddzielnych wątków
  • kod jest owinięta w Runnable który pasuje bliżej koncepcyjnie: ty "Nie piszę jakiegoś specjalnego rodzaju Nici, prawda? Wystarczy napisać kod, który można uruchomić/uruchomić.
  • można łatwo przełączać się przy użyciu Executor co dodatkowo streszczenie stąd decyzja

I last but not least Ci uniknąć ewentualnej pomyłki o tym, czy rodzimych zasobów gwint jest tworzony.

+0

masz na myśli mój wątek rozszerza wątek powodują ten problem?nawet jeśli po prostu wywołać run(), zamiast uruchomić? – cometta

+2

@cornetta - nie mówi, że powoduje problemy. Mówi, że "biedną praktyką" jest przedłużenie "Nici". –

+0

W tym samym duchu, dlaczego nie użyć Executora? –

4

gdy dzwonisz prowadzony metoda() żaden nowy wątek powinien zostać utworzony. A twoje obiekty będą zbierane przez Garbage collectora, gdy nie będą się do nich odwoływać.

Twoja inna część kodu może tworzyć wiele wątków.

Spróbuj użyć w kodzie ThreadPoolExecutor (buforowanie wątków), aby ograniczyć wątki w aplikacji, i odpowiednio dostosuj rozmiar wątków, aby uzyskać lepszą wydajność.

Można również sprawdzić następujące debugować problem: (określany z linku) Istnieje kilka rzeczy do zrobienia, jeśli wystąpi ten wyjątek.

  • Użyj polecenia PID lsof -p (Unix platformy), aby zobaczyć, jak wiele wątków są aktywne w tym procesie.
  • Ustal, czy liczba procesorów zdefiniowanych jako jest określona przez system operacyjny jako maksymalna liczba . Jeśli limit jest zbyt niski dla aplikacji, spróbuj podnieść limit wątków na proces.
  • Zbadaj kod aplikacji do ustalenia, czy istnieje kod, który jest tworząc nici lub połączenia (takie jako połączenia LDAP), a nie niszcząc je. Można zrzucić wątki Java , aby sprawdzić, czy istnieje nadmiarowy numer .
  • Jeśli okaże się, że zbyt wiele połączeń zostało otwartych przez aplikację, upewnij się, że każdy wątek tworzony przez aplikację jest zniszczony. Aplikacja korporacyjna (.ear) lub Web (.war) działa pod długo działającą maszyną JVM . Właśnie dlatego, że aplikacja została zakończona, nie oznacza to, że proces JVM się kończy. Jest konieczne, aby aplikacja zwolniła wszelkie przydzielone przez nią zasoby. Innym rozwiązaniem byłoby, aby aplikacja używała puli wątków do zarządzać potrzebnymi wątkami.
1

Ten link opisuje dość ładnie, jak ten błąd jest generowany przez JVM: http://javaeesupportpatterns.blogspot.ro/2012/09/outofmemoryerror-unable-to-create-new.html

Zasadniczo jest to bardzo zależy od systemu operacyjnego. Na RedHat Linux 6.5 (najprawdopodobniej inne wersje dystrybucji/wersji i jądra) max_threads = max_process x 2.

Maksymalna liczba wątków jest bardzo zależna od liczby dozwolonych procesów. Która maksymalna liczba procesów jest zależna od zainstalowanej maksymalnej pamięci fizycznej.

Jeśli zajrzeć do pliku limits.conf (na moim RHL 6.5 jest to plik /etc/security/limits.d/90-nproc.conf). Należy podać plik:

# Default limit for number of user's processes to prevent 
# accidental fork bombs. 
# See rhbz #432903 for reasoning. 

*   soft nproc  **1024** 
root  soft nproc  unlimited 

Zobaczysz, że dla użytkowników spoza domeny głównej jest to 1024 (co oznacza 2048 maksymalnych wątków).

Aby zobaczyć maksymalną liczbę wątków, które użytkownik może utworzyć, należy uruchomić polecenie "cat/proc/sys/kernel/threads-max" lub "sysctl kernel.threads-max".

Aby rozwiązać problem, jak to (przynajmniej to działało dla mnie) jako root musisz ncrease na max dopuszczalne wątki:

echo 10000>/proc/sys/kernel/gwinty-Max

Dotyczy to wszystkich użytkowników i root. Użytkownik musi się wylogować, a następnie zalogować ponownie, aby ustawienia zostały uwzględnione.

Powiązane problemy