为什么我不能构造一个由DelayQueue支持的ThreadPoolExecutor?

时间:2011-03-09 00:34:34

标签: java compiler-errors executors

我正在尝试创建一个ThreadPoolExecutor:

// Thingy implements Delayed and Runnable
ExecutorService executor = new ThreadPoolExecutor(1, 1, 0l, TimeUnit.SECONDS, new DelayQueue<Thingy>());

编译器说“找不到符号”:

symbol  : constructor ThreadPoolExecutor(int,int,long,java.util.concurrent.TimeUnit,java.util.concurrent.DelayQueue<Thingy>)

但我不明白 - DelayQueue实施BlockingQueue,所以我不应该使用this constructor吗?

3 个答案:

答案 0 :(得分:7)

这是一个泛型问题。您不能使用DelayQueue<Thingy>,它必须是DelayQueue<Runnable>,因为ThreadPoolExecutor构造函数未声明为接受Runnable子类型的队列。

答案 1 :(得分:1)

RunnableScheduledFuture是Runnable和Delayed,但无法转换为BlockingQueue<Runnable>。在The Java Tutorials

了解原因

查看ScheduledThreadPoolExecutor,它可以安排命令在给定延迟后运行,或定期执行。

答案 2 :(得分:0)

虽然这是一个老问题我想发布我的答案,因为我最近正在寻找这个解决方案。可以在ThreadPoolExecutor后面使用DelayQueue,它只需要一些代码包装。诀窍是让DelayQueue将自己呈现为BlockingQueue。

我首先定义了一个扩展DRRunnable的接口Delayed。请注意,此处的静态方法会创建DR的实例(实例类未显示)。

public interface DR extends Delayed, Runnable {    
    public static DR make( Runnable r )
    {
        if (r instanceof DR)
        {
            return (DR)r;
        }
        Impl impl = new Impl(r);
        if (r instanceof Delayed)
        {
            impl.expires = ((Delayed) r).getDelay( TimeUnit.MILLISECONDS );
        }
        return impl;
    }

    public static DR make( Runnable r, long expires )
    {
        if (r instanceof DR)
        {
            if (expires == ((DR)r).getDelay( TimeUnit.MILLISECONDS ))
            {
                return (DR)r;
            }
        }
        return new Impl(r, expires);
    }
}

实施应覆盖:public int compareTo(Delayed o)public boolean equals( Object o )public int hashCode()

创建一个扩展DelayQueue的类。此类添加一个方法,将DelayQuue显示为BlockingQueue。返回的类只包含DelayQueue并使用make接口的DR方法在必要时从Runnable转换为DR

public class DelayedBlockingQueue extends DelayQueue<DR>  {

    public BlockingQueue<Runnable> asRunnableQueue() {
        return new BlockingQueue<Runnable>(){
            DelayedBlockingQueue dbq = DelayedBlockingQueue.this;
            public boolean add(Runnable e) {
                return dbq.add( DR.make( e ));
            }

            private List<DR> makeList( Collection<? extends Runnable> coll)
            {
               return coll.stream().map( r -> DR.make( r ) ).collect( Collectors.toList() ) ;
            }

            public boolean addAll(Collection<? extends Runnable> arg0) {
                return dbq.addAll(makeList( arg0 ) );
            }

            public void clear() {
                dbq.clear();
            }

            public boolean contains(Object o) {
                if (o instanceof Runnable) { 
                    return dbq.contains( DR.make( (Runnable)o ) );
                } 
                return false;
            }

            public boolean containsAll(Collection<?> arg0) {
                List<DR> lst = new ArrayList<DR>();
                for (Object o : arg0)
                {
                    if (o instanceof Runnable)
                    {
                        lst.add(  DR.make(  (Runnable)o ) );
                    }
                    else {
                        return false;
                    }
                }

                return dbq.containsAll( lst );
            }

            public int drainTo(Collection<? super Runnable> c, int maxElements) {
                return dbq.drainTo( c, maxElements );
            }

            public int drainTo(Collection<? super Runnable> c) {
                return dbq.drainTo( c );
            }

            public Runnable element() {
                return dbq.element();
            }                

            public void forEach(Consumer<? super Runnable> arg0) {
                dbq.forEach( arg0 );
            }

            public boolean isEmpty() {
                return dbq.isEmpty();
            }

            public Iterator<Runnable> iterator() {
                return WrappedIterator.create( dbq.iterator() ).mapWith( dr -> (Runnable)dr );
            }

            public boolean offer(Runnable e, long timeout, TimeUnit unit) throws InterruptedException {
                return dbq.offer( DR.make( e ), timeout, unit );
            }

            public boolean offer(Runnable e) {
                return dbq.offer( DR.make( e ) );
            }

            public Runnable peek() {
                return dbq.peek();
            }

            public Runnable poll() {
                return dbq.poll();
            }

            public Runnable poll(long timeout, TimeUnit unit) throws InterruptedException {
                return dbq.poll( timeout, unit );
            }

            public void put(Runnable e) throws InterruptedException {
                dbq.put( DR.make(e) );
            }

            public int remainingCapacity() {
                return dbq.remainingCapacity();
            }

            public Runnable remove() {
                return dbq.remove();
            }

            public boolean remove(Object o) {
                if (o instanceof Runnable)
                {
                    return dbq.remove( DR.make(  (Runnable)o) );
                }
                return false;
            }

            public boolean removeAll(Collection<?> arg0) {
                List<DR> lst = new ArrayList<DR>();
                for (Object o : arg0)
                {
                    if (o instanceof Runnable)
                    {
                        lst.add(  DR.make(  (Runnable)o ) );
                    }

                }               
                return dbq.removeAll( lst );
            }

            public boolean retainAll(Collection<?> arg0) {
                return dbq.retainAll( arg0 );
            }

            public int size() {
                return dbq.size();
            }

            public Runnable take() throws InterruptedException {
                return dbq.take();
            }

            public Object[] toArray() {
                return dbq.toArray();
            }

            public <T> T[] toArray(T[] arg0) {
                return dbq.toArray( arg0 );
            }                
    };                       
}

要使用该解决方案,请创建DelayedBlockingQueue并使用asRunnableQueue()方法将runnable队列传递给ThreadPoolExecutor构造函数。

DelayedBlockingQueue queue = new DelayedBlockingQueue();
ThreadPoolExecutor execService = new ThreadPoolExecutor( 1, 5, 30, TimeUnit.SECONDS, queue.asRunnableQueue() );