2012-10-04 12 views
14

Ich habe viel gesucht, konnte aber keine Lösung finden. I Java-Thread-Pool in einer solchen Art und Weise verwendet werden:Angeben der Ausführung der Task-Reihenfolge in Java

ExecutorService c = Executors.newFixedThreadPool(3); 
for (int i = 0; i < 10; ++i) { 
    c.execute(new MyTask(i)); 
} 

In einer solchen Art und Weise Tasks in daraus folgenden Reihenfolge (wie in queue) ausgeführt werden. Aber ich muss die Strategie "Nächste Aufgabe auswählen" ändern. Daher möchte ich jedem Task eine Priorität zuweisen (es ist keine Threadpriorität) und Ausführungsaufgaben entsprechen diesen Prioritäten. Wenn der Executor eine andere Task beendet hat, wählt er die nächste Task als Task mit der höchsten Priorität. Es beschreibt häufiges Problem. Vielleicht gibt es einen einfacheren Ansatz, der keine Prioritäten berücksichtigt. Er wählt die zuletzt hinzugefügte Aufgabe als nächste auszuführende anstelle von zuerst hinzugefügte aus. Grob gesagt, verwendet FixedThreadPool FIFO-Strategie. Kann ich zum Beispiel die LIFO-Strategie verwenden?

Antwort

11

Sie PriorityBlockingQueue verwenden können Queue ThreadPoolExecutor angeben.

public class PriorityExecutor extends ThreadPoolExecutor { 

    public PriorityExecutor(int corePoolSize, int maximumPoolSize, 
      long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { 
     super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); 
    } 
    //Utitlity method to create thread pool easily 
    public static ExecutorService newFixedThreadPool(int nThreads) { 
     return new PriorityExecutor(nThreads, nThreads, 0L, 
       TimeUnit.MILLISECONDS, new PriorityBlockingQueue<Runnable>()); 
    } 
    //Submit with New comparable task 
    public Future<?> submit(Runnable task, int priority) { 
     return super.submit(new ComparableFutureTask(task, null, priority)); 
    } 
    //execute with New comparable task 
    public void execute(Runnable command, int priority) { 
     super.execute(new ComparableFutureTask(command, null, priority)); 
    } 
} 

Definieren Sie ComparableFutureTask, um die Priorität zu vergleichen.

class ComparableFutureTask<T> extends FutureTask<T> 
     implements 
      Comparable<ComparableFutureTask<T>> { 

    volatile int priority = 0; 

    public ComparableFutureTask(Runnable runnable, T result, int priority) { 
     super(runnable, result); 
     this.priority = priority; 
    } 
    public ComparableFutureTask(Callable<T> callable, int priority) { 
     super(callable); 
     this.priority = priority; 
    } 
    @Override 
    public int compareTo(ComparableFutureTask<T> o) { 
     return Integer.valueOf(priority).compareTo(o.priority); 
    } 
    } 
+0

+1 vielleicht ein Schnipsel geben, um dies besser zu machen. – Tudor

+5

Dies kann nicht funktionieren, weil 'newTaskFor' die ComparableFutureTask in eine FutureTask umschließt, die nicht vergleichbar ist. Sie müssen auch die zwei 'newTaskFor'-Methoden überschreiben. – assylias

+1

Siehe [dieser Beitrag] (http://Stackoverflow.com/a/16834473/829571) für ein einfaches Beispiel. – assylias

7

ThreadPoolExecutor Konstruktor akzeptiert Blocking. Sie können die Warteschlange als PriorityBlockingQueue übergeben. Es macht keinen Empfänger bei der Bestellung Sie müssen benutzerdefinierte Vergleicher übergeben, um die Ordnung zu erhalten.

static BlockingQueue<Task> queue=new PriorityBlockingQueue<Task>(MAXPOOL,new TaskComparator()); 

static ThreadPoolExecutor threadpool = new ThreadPoolExecutor(30, MAXPOOL, 
     MAXPOOL, TimeUnit.SECONDS, (PriorityBlockingQueue) queue, new mThreadFactory()); 



class TaskComparator implements Comparator<Task>{ 
    public int compare(Task t1, Task t2){ 
    //write you own logic to compare two task. 
    } 
} 
+1

Guter Beitrag, außer dass 'equals'' boolean' zurückgibt und 'compare' gibt' int' zurück . Ich denke, du wolltest 'compareTo' verwenden. – Tudor

+0

+1 danke für die Nachricht. –

Verwandte Themen