2012-05-04 14 views
6

Theo như tôi có thể hiểu từ tài liệu java.lang.Thread và từ các câu hỏi khác được đăng tại đây trên stackoverflow, như "How to access a Runnable object by Thread?" và "Get current instance of Runnable", bạn không thể tham chiếu đối tượng Runnable được nhúng trong Thread. Một kịch bản có khả năng này sẽ hữu ích là khi triển khai một phương thức, không thể sửa đổi chữ ký vì chúng tôi ghi đè phương thức được xác định trong lớp hoặc giao diện khác và yêu cầu phải thực hiện các hoạt động khác nhau tùy thuộc vào loại Runnable được nhúng trong số Thread hiện tại.Tại sao không thể có được Runnable được nhúng trong một Thread?

Nếu chúng ta có ví dụ một phương pháp gọi là getRunnable trong lớp Thread chúng ta có thể làm điều gì đó như thế này:

if (Thread.currentThread().getRunnable() instanceof Type1) { 
    // do something... 
} else { 
    // do something else... 
} 

Điều này có thể cũng hữu ích trong các tình huống khi chúng ta muốn đảm bảo các hoạt động chứa đựng trong một phương pháp được chỉ được thực hiện bởi một số chủ đề chứ không phải bởi các chủ đề khác. Vì vậy, tôi đã tự hỏi, là có một lý do cụ thể tại sao các nhà phát triển Java đã quyết định không cho phép để có được các trường hợp Runnable từ một Thread, hoặc nó là một tính năng còn thiếu đáng để được thông báo? Không. Nếu bạn nghĩ rằng không có lý do đằng sau lựa chọn đó nhưng không đáng để thông báo cho nó là thiếu tính năng, bạn sẽ sử dụng chiến lược nào trong kịch bản được mô tả ở trên?

+0

Điều gì sẽ là "Runnable" cho các chủ đề chính với các 'phương pháp main'? –

+2

@KirkWoll, 'null'? –

+4

Phân nhánh trên kết quả của 'instanceof' như bạn làm trong ví dụ của bạn gần như không bao giờ là một ý tưởng hay. – NPE

Trả lời

11

Vì vậy, tôi đã tự hỏi, là có một lý do cụ thể tại sao các nhà phát triển Java đã quyết định không cho phép để có được những ví dụ Runnable từ một chủ đề

Có lẽ chỉ không phải là một yêu cầu. Bản thân số Runnable sẽ có thể xác định được lớp riêng của nó để ý tưởng rằng nó cần để có được thông tin đó là lạ. Nó cũng có thể là một sự bảo vệ để các luồng khác không có quyền truy cập vào lớp đang chạy trong một luồng khác.

Nếu bạn cần truy cập vào Runnable hiện tại từ các phần khác của ứng dụng của bạn thì tôi khuyên bạn nên sử dụng ThreadLocal<Runnable>. Trong phương thức run() của bạn, bạn có thể đặt nó và sau đó lấy nó trong các lớp khác của bạn. Tuy nhiên, bạn cần đặt ThreadLocal ở đâu đó trên toàn cầu.

Bạn cũng có thể xử lý theo dõi ngăn xếp hiện tại để tìm ra lớp kèm theo Runnable thậm chí còn nhiều hơn một hack nhưng nó sẽ hoạt động.

5

Có một vài phương pháp tiếp cận bạn có thể làm để làm được việc này:

Giữ một bản đồ của Runnable của bạn đến Thread s được thực hiện chúng (hoặc với một Map<Thread, Runnable> hoặc với một ThreadLocal<Runnable>)
Sử dụng phản chiếu để truy cập Runnable từ Thread:

private static final Field target; 
static { 
    Field f = null; 
    try { 
     f = Thread.class.getDeclaredField("target"); 
     f.setAccessible(true); 
    } catch (NoSuchFieldException e) { 
     // might happen in a different version of Java (works in Java 7) 
     e.printStackTrace(); 
    } 
    target = f; 
} 

public static Runnable getTarget(Thread t) { 
    try { 
     return (Runnable) target.get(t); 
    } catch (IllegalAccessException e) { 
     // shouldn't happen, we already made the field accessible when we created it 
     e.printStackTrace(); 
     } 
    return null; 
} 
0

có một phương pháp gián tiếp có thể nó sẽ giúp đỡ, Bạn có thể lấy vết đống.

StackTraceElement[] stackTraceElement = thread.getStackTrace(); 
for(StackTraceElement e :stackTraceElement){ 
    System.out.println("Trace "+e.getClassName()); 
} 

Output:

vết java.lang.Chủ đề

vết com.emc.multithreading.RunnableDemo

vết java.lang.Thread