在ThreadPoolExecutor上实现PriorityQueue

时间:2015-06-01 13:25:55

标签: java priority-queue future threadpoolexecutor

现在已经挣扎了2天多了。

实现了我在这里看到的答案 Specify task order execution in Java

public class MyTask implements Runnable{

 public MyTask(File file, Context context, int requestId) {
    this._file = file;
    this.context = context;
    this.requestId = requestId;
}

@Override
public void run() {
      // some work
    } catch (IOException e) {
        Log.e("Callable try", post.toString());

    }
}

我使用的Runnable:MyTask

public class MediaDownloadService extends Service {

private DBHelper helper;
Notification notification;
HashMap<Integer,Future> futureTasks = new HashMap<Integer, Future>();
final int _notificationId=1;
File file;

@Override
public IBinder onBind(Intent intent) {
    return sharonsBinder;
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    helper = new DBHelper(getApplicationContext());
    PriorityExecutor executor = (PriorityExecutor) PriorityExecutor.newFixedThreadPool(3);
    Log.e("requestsExists", helper.requestsExists() + "");
   if(helper.requestsExists()){
        // map of the index of the request and the string of the absolute path of the request
        Map<Integer,String> requestMap = helper.getRequestsToExcute(0);
        Set<Integer> keySet = requestMap.keySet();
        Iterator<Integer> iterator = keySet.iterator();
        Log.e("MAP",requestMap.toString());
        //checks if the DB requests exists
        if(!requestMap.isEmpty()){
            //execute them and delete the DB entry
            while(iterator.hasNext()){
                int iteratorNext = iterator.next();
                Log.e("ITREATOR", iteratorNext + "");
                file = new File(requestMap.get(iteratorNext));
                Log.e("file", file.toString());
                Log.e("thread Opened", "Thread" + iteratorNext);
                Future future = executor.submit(new MyTask(file, this, iteratorNext),10);
                futureTasks.put(iteratorNext, future);
                helper.requestTaken(iteratorNext);
            }
            Log.e("The priority queue",executor.getQueue().toString());
        }else{

            Log.e("stopself", "stop self after this");
            this.stopSelf();
        }
    }
    return START_STICKY;
}

我的服务:MediaDownloadService

Caused by: java.lang.ClassCastException: java.util.concurrent.FutureTask cannot be cast to java.lang.Comparable
        at java.util.concurrent.PriorityBlockingQueue.siftUpComparable(PriorityBlockingQueue.java:318)
        at java.util.concurrent.PriorityBlockingQueue.offer(PriorityBlockingQueue.java:450)
        at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1331)
        at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:81)
        at com.vit.infibond.test.PriorityExecutor.submit(PriorityExecutor.java:26)
        at com.vit.infibond.test.MediaDownloadService.onStartCommand(MediaDownloadService.java:65)

在这一行上不断收到错误: 未来的未来= executor.submit(new MyTask(file,this,iteratorNext),10);

甚至是executor.submit();假设返回我不断获得的未来对象

{{1}}

任何人都能救我脱离这场噩梦吗?

我尝试过这样的答案 Testing PriorityBlockingQueue in ThreadPoolExecutor

仅添加forNewTask覆盖以再次获取强制执行,但这次是为RunnableFuture。

我理解我的理解中缺少一些基本的东西,并希望深入解释...

2 个答案:

答案 0 :(得分:2)

通过查看java.util.concurrent.ThreadPoolExecutor的源代码,在提交期货时让这项工作变得非常麻烦。你必须覆盖感觉内部的受保护方法,并做一些讨厌的演员。

我建议您只使用execute方法。 <{1}}没有包裹,所以它应该有效。

如果您需要等待工作结果,我建议您自己实施,以避免陷入Runnable内部问题。

答案 1 :(得分:2)

莎朗古尔在最底层建议的是改变

//execute with New comparable task
public void execute(Runnable command, int priority) {
    super.execute(new ComparableFutureTask(command, null, priority));
}

//execute with New comparable task
public ComparableFutureTask  execute(Runnable command, int priority) {
    ComparableFutureTask task = new ComparableFutureTask(command, null, priority);
    super.execute(task);
    return task;
}

然后在你的来电者中:

CurrentTask currentTask = new CurrentTask(priority,queue)
RunnableFuture task = enhancedExecutor.execute(currentTask,priority.value)
task?.get()

我遇到了问题

RunnableFuture task = myExecutor.submit(currentTask)
task?.get()

导致了currentTask转换为FutureTask并且不了解CurrentTask中的对象的问题。仅.execute一切都很好。这个黑客似乎是半/近足够的工作。

因为它完美地工作但没有生成文件

RunnableFuture task = myExecutor.execuute(currentTask)
    task?.get()

所以这就是我如何使它工作(优先处理两次)感觉不对,但有效......

CurrentTask ::

class CurrentTask implements Runnable {
    private Priority priority
    private MyQueue queue

    public int getPriority() {
        return priority.value
    }

    public CurrentTask(Priority priority,ReportsQueue queue){
        this.priority = priority
        this.queue=queue
    }

    @Override
    public void run() {
...
}
}

优先级:

public enum Priority {

    HIGHEST(0),
    HIGH(1),
    MEDIUM(2),
    LOW(3),
    LOWEST(4)

    int value

    Priority(int val) {
        this.value = val
    }

    public int getValue(){
        return value
    }
}

然后你的遗嘱执行人致电

public YourExecutor() {

    public YourExecutor() {
        super(maxPoolSize,maxPoolSize,timeout,TimeUnit.SECONDS, new PriorityBlockingQueue<Runnable>(1000,new ReverseComparator()))
    }

因此,在更改为新方法之前,提交命中下面的比较器并且由于TaskExecutor不理解.priority?.value这是默认的.execute currentTask是什么击中了这一切并且一切正常

public int compare(final Runnable lhs, final Runnable rhs) {

    if(lhs instanceof Runnable && rhs instanceof Runnable){
      // Favour a higher priority
        println "${lhs} vs ${lhs.getClass()}"
      if(((Runnable)lhs)?.priority?.value<((Runnable)rhs)?.priority?.value){
 ...
}

}

所以上面的hack及以下更改似乎正在运行

class  ReverseComparator implements Comparator<ComparableFutureTask>{

  @Override
  public int compare(final ComparableFutureTask lhs, final ComparableFutureTask rhs) {

    if(lhs instanceof ComparableFutureTask && rhs instanceof ComparableFutureTask){

        // run higher priority (lower numbers before higher numbers)
        println "${lhs} vs ${lhs.getClass()} ::: ${lhs.priority}"
      if(((Runnable)lhs)?.priority<((Runnable)rhs)?.priority){
          println "-returning -1"
        return -1;
      } else if (((Runnable)lhs)?.priority>((Runnable)rhs)?.priority){
      println "-returning @@@1"
        return 1;
      } 


    }
    println "-returning ==0 "
    return 0;
  }  

只是因为我们已经传递覆盖ComparableFutureTask,其优先级延伸FutureTask

希望现在有一天和现在有点意义:)