2011-09-04 19 views
7

Tôi có một vấn đề mà tôi không thực sự nghĩ rằng có một giải pháp nhưng tôi sẽ cố gắng ở đây anyway. Ứng dụng của tôi sử dụng một pool thread và một số luồng trong pool này có một biến cục bộ thread có thể kế thừa. Tôi đã mở rộng lớp ThreadPoolExecutor về cơ bản rõ ràng ra biến địa phương thread (trong phương thức gọi lại afterExecute) khi một luồng được thực hiện xong.InheritableThreadLocal và thread pools

Tôi hiểu rằng khi bạn có biến InheritableThreadLocal, phương thức childValue() được gọi khi thread được khởi tạo để lấy giá trị của biến ThreadLocal từ chuỗi gốc. Tuy nhiên, trong trường hợp của tôi, lần sau thread được sử dụng (sau khi được sử dụng một lần), giá trị của biến InheritableThreadLocal là null (vì nó đã bị xóa trước đó trong afterExecute). Có cách nào để truy cập biến chủ đề của thread thread trong beforeExecute để tôi về cơ bản có thể mô phỏng phương thức childValue trong InheritableThreadLocal có tại thời điểm tạo luồng không.

+1

Tại sao các bạn thanh toán bù trừ giá trị địa phương chủ đề thread con nếu bạn cần nó sau này? Có phải các giá trị cần thiết trong lần chạy tiếp theo từ một chuỗi gốc khác hoặc có thay đổi trong chuỗi gốc do chuỗi con đầu tiên được tạo không? –

+0

@Bert - đó là lý do chính xác. Về cơ bản tôi đang lưu trữ một id yêu cầu trong biến địa phương thread mà thay đổi trên nhiều sử dụng của các chủ đề con. – neesh

Trả lời

4

Có vẻ như đây là trường hợp sử dụng kém đối với hương vị "có thể kế thừa" của người dân địa phương.

Lời khuyên của tôi sẽ chỉ sử dụng thông thường TheadLocal và thực hiện việc khởi tạo một cách rõ ràng; ví dụ. chuyển giá trị ban đầu từ chuỗi gốc đến chuỗi con dưới dạng tham số hoặc thứ gì đó.

(Tôi đã đề xuất rằng bạn buộc khởi tạo chuỗi chỉ địa phương của chuỗi con bằng cách lấy giá trị đó ngay khi bắt đầu. Nhưng điều đó có nguy cơ một điều kiện chủng tộc, ví dụ: nếu chuỗi chủ đề được trả về hồ bơi trước khi thread con bắt đầu thực hiện.)


tôi đoán những gì tôi đang hỏi là nếu có một cách để truy cập giá trị của biến địa phương chủ đề thread của cha mẹ từ một sợi con.

Không có cách nào để thực hiện việc này.

Và, xét xử từ các nhận xét khác của bạn, tôi nghi ngờ rằng bạn có nghĩa là "cha mẹ" và "con" theo nghĩa thông thường ... nơi chuỗi chủ đề tạo chuỗi con.

Nhưng đây là một ý tưởng. Thay vì cố gắng chia sẻ một biến giữa các chuỗi, hãy chia sẻ một giá trị cố định (ví dụ: ID yêu cầu) và sử dụng nó làm khóa cho một số chia sẻ Map. Sử dụng các mục nhập Map làm biến được chia sẻ.

+1

cảm ơn phản hồi. Tôi tò mò làm thế nào tôi có thể buộc khởi tạo thread-local của thread con. Tôi đoán những gì tôi yêu cầu là nếu có một cách để truy cập vào giá trị của thread thread thread chủ đề của phụ huynh từ một chủ đề con. – neesh

+0

Thật không may câu trả lời này để lại vấn đề mở. Làm thế nào có thể một thread địa phương được chuyển từ một sợi khác.Nếu người đó là đứa trẻ của người kia thì các InheritableThreadLocals sẽ làm công việc một cách độc đáo, nhưng bạn làm gì trong trường hợp một nhóm luồng? – Gregor

+0

Tại sao bạn downvote câu trả lời? Đó là loại thô lỗ để downvote một câu trả lời mà nói rằng không có giải pháp tốt tồn tại ... chỉ vì bạn không thích thực tế đó. Chắc chắn, nó không khuyến khích tôi giúp bạn! –

0

Hàm khởi tạo của runnable chạy trong luồng của người gọi, trong khi phương thức chạy chạy trong chuỗi con. Bạn có thể sử dụng thực tế này để chuyển thông tin từ cha mẹ đến chuỗi con. Xem:

public class ThreadlocalApplication { 
static public ThreadLocal<String> tenantId = new ThreadLocal<>(); 

public static void main(String[] args) throws ExecutionException, InterruptedException { 
    ExecutorService executor = Executors.newCachedThreadPool(); 
    System.out.println(Thread.currentThread().getName()); 
    ThreadlocalApplication.tenantId.set("4711"); 
    executor.submit(new AsyncTask()).get(); 
    executor.shutdown(); 
} 

static class AsyncTask implements Runnable { 
    private String _tenantId; 

    public AsyncTask() { 
     System.out.println(Thread.currentThread().getName()); 
     _tenantId = ThreadlocalApplication.tenantId.get(); 
    } 

    @Override 
    public void run() { 
     ThreadlocalApplication.tenantId.set(_tenantId); 
     System.out.println(Thread.currentThread().getName()); 
     System.out.println(ThreadlocalApplication.tenantId.get()); 
    } 
} 
} 

Và đây là kết quả

main 
main 
pool-1-thread-1 
4711 
Các vấn đề liên quan