2015-06-24 22 views
6

Tôi có một chương trình java trong đó có 13 chủ đề, mặc dù chỉ có một trong số họ là 99% sử dụng CPU và đã chạy trong ~ 24 giờ. Những người khác đang ở mức sử dụng CPU 0,0% và hiển thị một số TIME+ ở bất kỳ đâu từ 0:00.0 đến 0:12.82 và một có 3:51.48. Chương trình này được dự định là một chương trình luồng đơn, vì vậy tôi tự hỏi tại sao các luồng khác lại có?Tại sao một chương trình java đơn luồng có quá nhiều luồng?

Họ đang làm gì và tại sao họ hiển thị quá ít sử dụng CPU và TIME +?

UPDATE: Tôi có một chương trình java cũ tôi đã viết (chương trình đầu tiên - không phán xét tôi!) Là đơn ren và cho thấy cùng một loại sử dụng chủ đề ...

import java.io.*; 

class xdriver { 
    static int N = 100; 
    static double pi = 3.141592653589793; 
    static double one = 1.0; 
    static double two = 2.0; 

    public static void main(String[] args) { 
    //System.out.println("Program has started successfully\n"); 

    if(args.length == 1) { 
     // assume that args[0] is an integer 
     N = Integer.parseInt(args[0]); 
    } 

    // maybe we can get user input later on this ... 
    int nr = N; 
    int nt = N; 
    int np = 2*N; 

    double dr = 1.0/(double)(nr-1); 
    double dt = pi/(double)(nt-1); 
    double dp = (two*pi)/(double)(np-1); 

    System.out.format("nn --> %d\n", nr*nt*np); 

    if(nr*nt*np < 0) { 
     System.out.format("ERROR: nr*nt*np = %d(long) which is %d(int)\n", (long)((long)nr*(long)nt*(long)np), nr*nt*np); 
     System.exit(1); 
    } 

    // inserted to artificially blow up RAM 
    double[][] dels = new double [nr*nt*np][3]; 

    double[] rs = new double[nr]; 
    double[] ts = new double[nt]; 
    double[] ps = new double[np]; 

    for(int ir = 0; ir < nr; ir++) { 
     rs[ir] = dr*(double)(ir); 
    } 
    for(int it = 0; it < nt; it++) { 
     ts[it] = dt*(double)(it); 
    } 
    for(int ip = 0; ip < np; ip++) { 
     ps[ip] = dp*(double)(ip); 
    } 

    double C = (4.0/3.0)*pi; 
    C = one/C; 

    double fint = 0.0; 
    int ii = 0; 
    for(int ir = 0; ir < nr; ir++) { 
     double r = rs[ir]; 
     double r2dr = r*r*dr; 
     for(int it = 0; it < nt; it++) { 
     double t = ts[it]; 
     double sint = Math.sin(t); 
     for(int ip = 0; ip < np; ip++) { 
      fint += C*r2dr*sint*dt*dp; 

      dels[ii][0] = dr; 
      dels[ii][1] = dt; 
      dels[ii][2] = dp; 
     } 
     } 
    } 

    System.out.format("N ........ %d\n", N); 
    System.out.format("fint ..... %15.10f\n", fint); 
    System.out.format("err ...... %15.10f\n", Math.abs(1.0-fint)); 
    } 
} 
+0

Một số có thể liên quan đến Bộ sưu tập rác. Đó là loại chương trình gì? Nó có GUI không? –

+2

Vui lòng đăng chương trình của bạn! – ganeshvjy

+0

Không có GUI - Tôi đang chỉ định '-XX: ParallelGCThreads = 1 -XX: + UseConcMarkSweepGC' vì vậy nó là GC đơn luồng. – drjrm3

Trả lời

4

Trích dẫn cuộc thảo luận được thực hiện here và các nghiên cứu khác.

Rất ít đề JVM lõi:

  1. Đính kèm Thính giả: Đây là chủ đề mà luôn luôn lắng nghe cho chủ đề JVM khác để gửi một yêu cầu. Một ví dụ thực tế là trong trường hợp hồ sơ hoặc (tôi không về điều này mặc dù) sản xuất các công cụ giám sát ứng dụng cấp như DynaTrace.
  2. Bộ điều phối tín hiệu: Khi hệ điều hành tăng tín hiệu cho JVM, chuỗi điều phối tín hiệu sẽ chuyển tín hiệu đến bộ xử lý thích hợp.
  3. Trình xử lý tham chiếu: Chủ đề mức ưu tiên cao để enqueue đang chờ Tham khảo. GC tạo một danh sách liên kết đơn giản các tham chiếu cần được xử lý và luồng này nhanh chóng thêm chúng vào hàng đợi thích hợp và thông báo cho người nghe ReferenceQueue.
  4. Trình kết thúc: Trình hoàn tất gọi phương thức finalizer.
  5. DestroyJavaVM: Chuỗi này dỡ bỏ máy ảo Java khi thoát chương trình. Hầu hết thời gian cần chờ đợi.
  6. Bộ thu gom rác: Chủ đề chịu trách nhiệm về cơ chế thu gom rác của Java, tùy thuộc vào việc GC có được bật hay không.
  7. chính: Chủ đề chính đang chạy chương trình của bạn chứa phương pháp main.

Một điểm quan trọng cần lưu ý là nó sẽ phụ thuộc vào việc triển khai JVM mà bao nhiêu và đó tất cả các chủ đề cốt lõi nó sẽ bắt đầu nhưng ngay cả khi chương trình Java được viết là một luồng duy nhất, sẽ có nhiều hơn một luồng trong JVM.

Chương trình Java có thể là luồng đơn nhưng JVM (sẽ chạy chương trình Java do người dùng xác định) đa luồng và sẽ có (ít nhất là cho JVM mới nhất) nhiều hơn một chuỗi ngay cả khi bắt đầu.

Dưới đây là một bản chụp của Java HotSpot (TM) Khách hàng VM phiên bản 24,55-b03 của tôi, chạy một luồng chương trình Java duy nhất:

Để trả lời câu hỏi của bạn

họ đang làm gì và tại sao họ có hiển thị quá ít sử dụng CPU và THỜI GIAN +?

phần gì: Có bắt đầu cho một mục đích bởi JVM, như đã giải thích ở trên như JVM muốn nghe nếu có hồ sơ hoặc chương trình giám sát muốn được một số chi tiết từ JVM.
Tại sao một phần: Vì chúng thực sự không hoạt động hoặc đang chạy, chúng đang ở trạng thái chờ hoặc đậu (xem chủ đề màu vàng trong ảnh chụp đính kèm của tôi, nếu bạn có ứng dụng giám sát GUI thì bạn cũng sẽ thấy Vàng hoặc khác nếu lệnh dòng sau đó luồng trong trạng thái WAIT) và do đó chúng không chiếm bất kỳ hoặc ít nhất các chu kỳ CPU và do đó ít sử dụng CPU hơn. Một lần nữa TIME+ sẽ hiển thị cho bạn thời gian cho chúng đã hoạt động và vì chúng không hoạt động, thông số này cũng ít hơn.

Hy vọng điều này sẽ hữu ích!

enter image description here

2

đề Nhiều khả năng đã được tạo ra ở đâu đó và không bao giờ được sử dụng.

Ví dụ:

ExecutorService es = Executors.newFixedThreadPool(12); 
// burn cpu, using only one thread (main) 
int i = 0; 
while(true) { 
    i++; 
} 
1

TIME+ từ trên là số lượng thời gian CPU dành. Một giải thích là nếu một quá trình liên tục bị chặn hoặc luôn bị chặn hơn, nó sẽ có cả mức sử dụng CPU thấp và mức thấp TIME+.

10

Bắt đầu chương trình Java có nghĩa là bắt đầu một JVM và cho biết lớp chính nào sẽ chạy (thường có phương pháp chính tĩnh).

JVM này sinh ra một số chủ đề nền ngoài chuỗi chính được đề cập ở trên.

Trong số đó là

  • Các VM chủ đề: Một chủ đề quan sát mà chờ đợi cho các nhiệm vụ đòi hỏi VM được tại một điểm an toàn. Ví dụ, có một nhiệm vụ thu gom rác hoàn toàn "ngăn chặn thế giới". Nhưng có những người khác.
  • Chủ đề GC: Một số luồng được duy trì để chạy bộ sưu tập rác.
  • Biên dịch chuỗi: Các chủ đề này được sử dụng để biên dịch mã byte thành mã máy gốc.

Có thể còn nhiều hơn thế nữa.

Ngoài ra, nếu bạn đang sử dụng AWT hoặc Swing, bạn sẽ nhận được một số chủ đề khác từ các khuôn khổ này. Một trong số đó là cái gọi là bộ điều phối sự kiện (EDT). Và - tất nhiên - có thể có chuỗi mà bạn đã tạo và chạy: bộ tính giờ, trình thực thi hoặc chỉ đơn giản là một số chuỗi tùy ý. Ngay cả đối với một ứng dụng chào đơn giản thế giới, có thể có hàng chục chủ đề đang chạy.

Nhưng hầu hết các chủ đề này chờ đợi nhiều hơn là làm điều gì đó. Vì vậy, rất có thể là cao mà chỉ có một sợi là thực sự làm việc, do đó sử dụng một số CPU.

Mặc dù ... Việc sử dụng CPU 100% có thể là một chỉ báo về một số vấn đề. Ví dụ, một vòng lặp không bao giờ kết thúc. Bạn phải sử dụng một hồ sơ để tìm hiểu những gì thực sự xảy ra. Nhưng nó có thể chỉ đơn giản là một chương trình có sử dụng CPU như vậy. Bản án của bạn.

+0

@ Laurbert515 Bạn có thể muốn sử dụng jvisualvm hiển thị các chủ đề có tên. Và nó cho phép bạn hiển thị chuỗi kết xuất cho bạn biết mã/lớp nào đang chạy trong luồng – Marged

+0

Không liên quan: hôm nay tôi (hy vọng) nhận được vàng huyền thoại ... chỉ nói lời cảm ơn đến tất cả những người tôi đã học được rất nhiều. .. – GhostCat

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