DelayQueue, ThreadPoolExecutor, Generics n' a cast O'My w/concurrent packag

Everyone,

I have been looking at this all day. This example runs, but I have a cast where a Generic should be enough. I think my problem starts with the ShortTask object which because I want to slam this in the DelayQueue it needs to implement Delayed as seen below:

public class ShortTask implements Runnable, Delayed {

My ShortTask object is contrived and lame, but just know it needs to go into the DelayQueue.

Okay then in my other GenerateTasks object I create a bunch of ShortTasks and add them to the DelayQueue...my problem is this:

I add the ShortTasks into the DelayQueue which is Generic'd (Is that even a word) as ShortTask as seen next:

delayQue = new DelayQueue<ShortTask>();

The add works swimingly , however I need to cast as seen at the end of the Constructor for the ThreadPoolExecuto (in bold for easy spotting):

threadPoolExecutor = new ThreadPoolExecutor(1, 1, 100L, TimeUnit.MILLISECONDS, <b>(BlockingQueue)</b>delayQue);

How do I get rid of that cast, and enable Generics since the custructor wants a Runnable.

I see this other post http://forum.java.sun.com/thread.jspa?threadID=620333 . but it did not help me out since the Concurrent package seems to enforce Generics which is good, but...well...this is driving me crazy.

Also since my ShortTask implements Runnable why does using the Generic ShortTask not work, why do I have to cast it since the Generic is <ShortTask> and a ShortTask implements Runnable?

Oh esteemed programmers that are so much smarter then me, please help me, and enlighten me, or just tell me I am dumb for asking something that is probably so simple I will cry when I am shown it.

Have a great day!!!!

import java.util.Iterator;

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.DelayQueue;

import java.util.concurrent.Delayed;

import java.util.concurrent.FutureTask;

import java.util.concurrent.ThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

publicclass GenerateTasksimplements Runnable{

private DelayQueue<ShortTask> delayQue =null;

private ThreadPoolExecutor threadPoolExecutor =null;

privateint tasksToGenerate = 10;

public GenerateTasks()

{

delayQue =new DelayQueue<ShortTask>();

threadPoolExecutor =new ThreadPoolExecutor(1, 1, 100, TimeUnit.MILLISECONDS, (BlockingQueue)delayQue);

threadPoolExecutor.prestartCoreThread();

}

publicvoid run(){

for (int c = 0, d = tasksToGenerate; c < tasksToGenerate; c++, d--){

ShortTask shortTask =new ShortTask("Task: " + c, d * 1000);

delayQue.add(shortTask);

}

}

publicstaticvoid main(String args[]){

Thread thread =new Thread(new GenerateTasks());

thread.start();

try{

synchronized(thread)

{

new Thread().sleep(12000);

}

}catch (InterruptedException e){

e.printStackTrace();

}

System.err.println("Finishing Run");

}

}

import java.util.Date;

import java.util.concurrent.Delayed;

import java.util.concurrent.TimeUnit;

publicclass ShortTaskimplements Runnable, Delayed{

private String name =null;

privatelong waitTime = 0;

privatelong startTime = 0;

public ShortTask(String name,int waitTime)

{

this.name = name;

this.waitTime = waitTime;

this.startTime = System.currentTimeMillis();

}

publicvoid run(){

try{

System.err.println("Cause this is lame, " + name +", " + waitTime);

System.err.println(new Date());

synchronized(this)

{

new Thread().sleep(100);

}

}catch (InterruptedException e){

// TODO Auto-generated catch block

e.printStackTrace();

}

}

public String toString()

{

StringBuilder stringBuilder =new StringBuilder();

stringBuilder.append("Name: ");

stringBuilder.append(name);

stringBuilder.append(" waiting " );

stringBuilder.append(waitTime);

stringBuilder.append("ms. ");

stringBuilder.append("Start Time: ");

stringBuilder.append(startTime);

return stringBuilder.toString();

}

publiclong getDelay(TimeUnit unit){

long currentTime = System.currentTimeMillis();

return unit.convert(startTime + waitTime - currentTime, TimeUnit.NANOSECONDS);

}

publicint compareTo(Delayed o){

return (int)(getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS));

}

}

[7950 byte] By [Jim_Tyrrella] at [2007-11-27 4:29:07]
# 1

A DelayQueue<ShortTask> is a BlockingQueue<ShortTask>, not a BlockingQueue<Runnable> which the ThreadPoolExecutor constructor needs. These are not the same for the same reason that a List<ShortTask> is not a List<Runnable>. You can add arbitrary Runnables to the latter, but not the former.

Try:private DelayQueue<Runnable> delayQue = null;

Alex

AlexHudsa at 2007-7-12 9:38:01 > top of Java-index,Core,Core APIs...
# 2

Alex,

Thank you for the response. I had also tried that, but then I get the following warning, which is basically the same as before, I did get rid of the cast though. So now I have a problem with the line "delayQue = new DelayQueue();", which obviously wants to see a "delayQue = new DelayQueue<Runnable>();", but no matter what I try it complains

For Ex:

delayQue = new DelayQueue();

Results in "Type Saftey, The expression of type DelayQueue needs unchecked conversion to conform to BlockingQueue<Runnnable>

delayQue = new DelayQueue<Runnable>();

Results in "Bound Mismatch, The type runnable is not a valid subsititue for the bounded parameter <E extends Delayed> of the type DelayQueue<E>.

delayQue = new DelayQueue<ShortTask>();

Results in the same as the one just above, and

"Type Mismatch: cannot convert from DelayQueue<ShortTask> to BlockingQueue<Runnable>

Anyone, Alex, Bueller with any ideas?

private BlockingQueue<Runnable> delayQue = null;

private ThreadPoolExecutor threadPoolExecutor = null;

private int tasksToGenerate = 10;

public GenerateTasks()

{

delayQue = new DelayQueue();

threadPoolExecutor = new ThreadPoolExecutor(1, 1, 100, TimeUnit.MILLISECONDS, delayQue);

Jim_Tyrrella at 2007-7-12 9:38:01 > top of Java-index,Core,Core APIs...
# 3

Ah, yes. Didn't spot that. Looking at it, It seems a shame that an Executor isn't parameterised by the type of Runnable you want to it to accept. It seems that that would filter through nicely and allow you to do what you want.

I can't actually find a safe way to modify your code. However, maybe you could do something with ScheduledThreadPoolExecutor instead? That allows you to execute tasks with delay.

As an aside, Thread.sleep is a static method which makes the current thread sleep, so you shouldn't use new Thread().sleep(). I don't see why you need a separate thread to generate the tasks either, but then I'm not seeing the whole picture.

Cheers,

Alex

AlexHudsa at 2007-7-12 9:38:01 > top of Java-index,Core,Core APIs...
# 4

Alex,

Yeah, well I guess I have come to the same conclusion. So is this a problem with Generics, is this a bug, do I just live with this? Should I cross post to the Generics list?

I really feel like I have found a big hoie, just not sure if it is the one that is in my head?

Thank You

Jim Tyrrell

Jim_Tyrrella at 2007-7-12 9:38:01 > top of Java-index,Core,Core APIs...
# 5

Hi Jim,

It looks to me that the previous post you mentioned almost exactly matches our discussion:

http://forum.java.sun.com/thread.jspa?threadID=620333

They ended up with the cast to a raw BlockingQueue as well. That's might be ok in practice, but dangerous because you could call execute with a Runnable that isn't a ShortTask and therefore shouldn't be in the queue. Ah well.

Alex

Message was edited by:

AlexHuds

AlexHudsa at 2007-7-12 9:38:01 > top of Java-index,Core,Core APIs...
# 6

Alex,

Yeah I saw that and posted it in the original question and tried to make that work, Generics got in the way of that also. That was a case of the Comparable not being good enough for getting into the PriorityQueue. I think between our discussion, and some more thoughts I think I have a bug. I think the Delayed Interface needs to enable a Generic..not sure if that is the correct terminolgy, but that is why this particular post did not solve this for me.

Thank You

Jim_Tyrrella at 2007-7-12 9:38:01 > top of Java-index,Core,Core APIs...