2010-08-17 25 views
6

tôi thấy bình luận như thế nàyjava.lang.OutOfMemoryError: không thể tạo chủ đề quê hương mới

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

trên Sun Java Forums

Trong ứng dụng của tôi, khởi tạo là chúng tôi dự định sử dụng thread, nhưng sau đó, chúng tôi quyết định không cần nữa, vì vậy chúng ta chỉ cần gọi run() thay vì start(). Chúng ta có cần thực hiện GC thủ công cho threadClass mới (..) không?

tomcat tôi thiết

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

Nhưng, nếu bạn thực hiện run() thay vì start() thì JVM sẽ không tạo chuỗi mới. Phải không? – sourcerebels

+0

đã đồng ý. vì vậy mặc dù tôi sử dụng new threadClass (..) trên phương pháp lớp dịch vụ của tôi, không cần phải làm sạch thủ công? – cometta

+0

Tại sao bạn cần tạo Chủ đề bên trong Tomcat (máy chủ web)? Nó không được khuyến khích. Hãy thử tìm một giải pháp thay thế: 1) một quá trình độc lập riêng biệt với các luồng giao tiếp thông qua RMI, JMS hoặc một cơ sở dữ liệu; 2) có thể sử dụng MessageDrivenBeans và JMS bên trong ứng dụng web của bạn, nếu bạn đồng ý với việc thay đổi sang một máy chủ ứng dụng J2EE như JBoss, Glassfish hoặc Geronimo; 3) khác ... :) – helios

Trả lời

11

Tại sao bạn tạo một Thread ngay từ đầu?

Mã của bạn nên triển khai giao diện Runnable thay thế.

Sau đó, khi bạn quyết định rằng bạn muốn chạy nó trong một chuỗi, hãy khởi tạo một đơn giản Thread với đối số Runnable làm đối số và gọi start() trên đối tượng Thread.

Nếu, thay vào đó, bạn chỉ muốn chạy nó trong chuỗi hiện tại của mình, chỉ cần gọi run() trên đối tượng Runnable của bạn.

này có một số ưu điểm:

  • bạn không liên quan đến bất kỳ Thread đối tượng miễn là bạn không quan tâm đến chủ đề riêng biệt
  • mã của bạn được gói trong một Runnable mà phù hợp chặt chẽ hơn khái niệm: bạn 'không viết một số loại đặc biệt của chủ đề, phải không? Bạn chỉ cần viết một số mã có thể được thực hiện/chạy.
  • bạn có thể dễ dàng chuyển sang sử dụng một Executor đó tiếp tục trừu tượng đi những quyết định

Và cuối cùng nhưng không kém phần quan bạn tránh bất kỳ sự nhầm lẫn tiềm năng về việc có hay không một nguồn lực chủ đề có nguồn gốc được tạo ra.

+0

bạn có nghĩa là threadClass của tôi mở rộng Thread gây ra vấn đề này?mặc dù tôi chỉ gọi run(), thay vì bắt đầu? – cometta

+2

@cornetta - anh ấy không nói rằng nó gây ra vấn đề. Anh ấy nói rằng đó là * thực hành kém * để mở rộng 'Chủ đề'. –

+0

Ngoài ra, trong cùng một tĩnh mạch, tại sao không sử dụng một Executor? –

4

Khi bạn gọi chạy() phương pháp không có chủ đề mới nên được tạo ra khởi động. Và đối tượng của bạn sẽ được thu thập bởi Garbage collector khi chúng không được tham chiếu.

Một phần mã khác của bạn có thể đang tạo nhiều Chủ đề.

Hãy thử sử dụng ThreadPoolExecutor (nhóm luồng) trong mã của bạn để giới hạn chủ đề trong ứng dụng của bạn, Và điều chỉnh kích thước luồng cho phù hợp để có hiệu suất tốt hơn.

Bạn cũng có thể kiểm tra sau để gỡ lỗi vấn đề của mình: (được tham chiếu từ liên kết) Có một số việc cần làm nếu bạn gặp ngoại lệ này.

  • Sử dụng lệnh PID lsof -p (Unix nền tảng) để xem có bao nhiêu bài đang hoạt động cho quá trình này.
  • Xác định xem có tối đa số luồng cho mỗi quy trình được xác định bởi hệ điều hành hay không. Nếu giới hạn quá thấp cho ứng dụng, hãy thử tăng giới hạn chuỗi cho mỗi quy trình.
  • Kiểm tra mã ứng dụng để xác định xem có mã nào là tạo chủ đề hoặc kết nối (chẳng hạn làm kết nối LDAP) và không hủy phá hủy chúng. Bạn có thể hủy các chuỗi Java để xem có số lượng quá đã được tạo hay không.
  • Nếu bạn thấy có quá nhiều kết nối được mở bởi ứng dụng, hãy thực hiện chắc chắn rằng bất kỳ chuỗi nào mà ứng dụng tạo sẽ bị hủy. An ứng dụng doanh nghiệp (.ear) hoặc Web ứng dụng (.war) chạy theo một liên kết dài JVM. Chỉ vì ứng dụng được hoàn thành không có nghĩa là rằng quá trình JVM kết thúc. Đó là bắt buộc rằng một ứng dụng miễn phí bất kỳ tài nguyên nào mà nó phân bổ. Một giải pháp khác là dành cho ứng dụng để sử dụng hồ bơi chuỗi để quản lý các chuỗi cần thiết.
1

liên kết này mô tả khá độc đáo như thế nào lỗi này được ném bởi JVM: http://javaeesupportpatterns.blogspot.ro/2012/09/outofmemoryerror-unable-to-create-new.html

Về cơ bản nó rất phụ thuộc vào hệ điều hành. Trên RedHat Linux 6.5 (rất có thể là phiên bản/phiên bản hạt nhân và phiên bản khác) max_threads = max_process x 2.

Số lượng chủ đề tối đa phụ thuộc vào số lượng quy trình cho phép. Số lượng tối đa các quy trình phụ thuộc vào bộ nhớ vật lý tối đa bạn đã cài đặt.

Nếu bạn có một cái nhìn trong tập tin limits.conf (trên RHL 6.5 của tôi nó nằm trong /etc/security/limits.d/90-nproc.conf). Hãy điền vào tệp:

# 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 

Bạn sẽ thấy rằng đối với người dùng không phải là người dùng gốc là 1024 (có nghĩa là chủ đề tối đa 2048).

Để xem số lượng chủ đề tối đa mà người dùng của bạn được phép tạo lệnh này "cat/proc/sys/kernel/threads-max" hoặc "sysctl kernel.threads-max".

Để giải quyết một vấn đề như thế này (ít nhất là nó làm việc cho tôi) như là người chủ, bạn sẽ cần phải ncrease tối đa cho phép chủ đề:

vang 10000>/proc/sys/kernel/đề-max

Điều này ảnh hưởng đến tất cả người dùng và gốc. Người dùng cần phải đăng xuất và sau đó đăng nhập lại để các cài đặt có hiệu lực.

Các vấn đề liên quan