2014-07-08 16 views
5

Ho una variazione del seguente codice:Come posso rendere compatibile il mio codice generico con questa firma del metodo?

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); 
    } 
} 

E come potete vedere, la mia coda non è compatibile con il costruttore ThreadPoolExecutor. C'è un modo per ovviare a questo rispetto a trasmettere la mia coda a (BlockingQueue<Runnable>)? Ovviamente non posso applicare la libreria standard Java.

+3

Perché stai utilizzando 'BlockingQueue ' in primo luogo? –

+0

Perché ho determinati runnables con priorità più alta. Ho saltato la parte di confronto nel mio esempio, perché non è correlata alla mia domanda. – Ztyx

+2

Se non è correlato, forse potresti semplicemente usare 'PriorityBlockingQueue '? Non è come se PriorityBlockingQueue smettesse di ordinarli se lo fai. –

risposta

7

No, e non si dovrebbe.

Il tuo BlockingQueue<MyRunnable> dovrebbe, ovviamente, contenere solo MyRunnable s. Ma lo ThreadPoolExecutor può inviare arbitrariamente attività alla coda che gli viene assegnata: vedere execute(Runnable command).

Se ciò si verifica, è possibile che un'istanza non sia MyRunnable nella coda. Quindi si tenta di eseguire il polling dal proprio riferimento di quella coda (digitata come BlockingQueue<MyRunnable>) e ottenere uno ClassCastException.

semplice esempio:

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 

Il codice qui sopra un'eccezione se l'queue.poll() accade prima che il pool di thread ha avuto la possibilità di annullare l'accodamento l'istanza WhateverRunnable.

+0

Il codice precedente non verrà compilato con un errore di compilazione sulla seconda riga secondo il mio esempio. – Ztyx

+0

Sì, hai ragione. Ma se hai aggiunto il cast esplicito, sarebbe - e sarebbe pericoloso per le ragioni che ho citato. Ecco perché il sistema di tipi non ti consente di farlo (almeno non senza il cast esplicito e persino il. Ti avvertirà che il cast non è sicuro) – yshavit

Problemi correlati