简体   繁体   中英

How can I make my generics code compatible with this method signature?

I have a variation of the following code:

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

And as you can see, my queue is not compatible with the ThreadPoolExecutor constructor. Is there any way to work around this than cast my queue to (BlockingQueue<Runnable>) ? I obviously can't patch Java Standard Library.

No, and you shouldn't .

Your BlockingQueue<MyRunnable> should, of course, only contain MyRunnable s. But the ThreadPoolExecutor can submit arbitrary Runnable tasks to the queue you give it: see execute(Runnable command) .

If that happens, you could have a non- MyRunnable instance in your queue. You then try to poll from your reference of that queue (typed as a BlockingQueue<MyRunnable> ), and get a ClassCastException .

Simple example:

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

The above code will throw an exception if the queue.poll() happens before the thread pool has had a chance to dequeue the WhateverRunnable instance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM