2014-07-08 13 views
5

Tôi có một biến thể của mã sau:Làm thế nào tôi có thể làm cho mã generics của tôi tương thích với chữ ký phương thức này?

package com.test.package; 

import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.PriorityBlockingQueue; 
import java.util.concurrent.ThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 

public class TestClass { 

    public static class MyRunnable implements Runnable { 

     @Override 
     public void run() { 
      System.out.println("Called"); 
     } 

    } 

    public void method() { 
     PriorityBlockingQueue<MyRunnable> queue = new PriorityBlockingQueue<MyRunnable>(); 
     method2(queue); 
    } 

    public void method2(BlockingQueue<? extends Runnable> queue) { 
     System.out.println(queue); 

     // Getting error here because BlockingQueue<? extends Runnable> is not a 
     // subtype of BlockingQueue<Runnable>. 
     ThreadPoolExecutor threadPool = new ThreadPoolExecutor(200, 200, 0L, 
      TimeUnit.MILLISECONDS, queue); 
    } 
} 

Và như bạn có thể thấy, hàng đợi của tôi là không tương thích với các nhà xây dựng ThreadPoolExecutor. Có cách nào để làm việc xung quanh này hơn là xếp hàng đợi của tôi đến (BlockingQueue<Runnable>)? Tôi rõ ràng không thể vá Java Standard Library.

+3

Tại sao bạn sử dụng 'BlockingQueue 'ở địa điểm đầu tiên? –

+0

Bởi vì tôi có các runnables nhất định với mức độ ưu tiên cao hơn. Tôi bỏ qua phần so sánh trong ví dụ của tôi, bởi vì nó không liên quan đến câu hỏi của tôi. – Ztyx

+2

Nếu nó không liên quan, có thể bạn chỉ cần sử dụng 'PriorityBlockingQueue '? Nó không giống như 'PriorityBlockingQueue' sẽ ngừng phân loại chúng nếu bạn làm điều đó. –

Trả lời

7

Không, và bạn không nên.

Tất nhiên, BlockingQueue<MyRunnable> của bạn chỉ nên chứa MyRunnable s. Tuy nhiên, ThreadPoolExecutor có thể gửi tùy ý Runnable tác vụ đến hàng đợi bạn cung cấp: xem execute(Runnable command).

Nếu điều đó xảy ra, bạn có thể có phiên bản không phải là MyRunnable trong hàng đợi của mình. Sau đó, bạn cố gắng thăm dò ý kiến ​​từ tham chiếu của bạn về hàng đợi đó (được nhập là BlockingQueue<MyRunnable>) và nhận được ClassCastException.

đơn giản ví dụ:

PriorityBlockingQueue<MyRunnable> queue = new PriorityBlockingQueue<>(); 
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(200, 200, 0L, 
     TimeUnit.MILLISECONDS, queue); 
threadPool.execute(new WhateverRunnable()); 
MyRunnable myRunnable = queue.poll(); // this could throw ClassCastException 

Đoạn mã trên sẽ ném một ngoại lệ nếu queue.poll() xảy ra trước khi các hồ bơi thread đã có một cơ hội để dequeue sơ thẩm WhateverRunnable.

+0

Đoạn mã trên sẽ không biên dịch với một lỗi biên dịch trên dòng thứ hai theo ví dụ của tôi. – Ztyx

+0

Vâng, bạn nói đúng. Nhưng nếu bạn thêm diễn viên rõ ràng, nó sẽ - và nó sẽ nguy hiểm vì những lý do tôi đã đề cập. Đó là lý do tại sao hệ thống kiểu không cho phép bạn làm điều đó (ít nhất là không phải không có diễn viên rõ ràng, và thậm chí là. Nó sẽ cảnh báo bạn rằng dàn diễn viên không an toàn) – yshavit

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