我正在尝试创建一个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吗?
答案 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。
我首先定义了一个扩展DR
和Runnable
的接口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() );