2017-11-16 4 views
1

Ich möchte die Task wissen, die vom Executor abgelehnt wird. Zum Beispiel möchte ich den Namen der abgelehnten Aufgabe bekommen. Aber in der RejectedExecutionHandler kann ich das nicht tun!Wie erhalte ich das Feld der Aufgabe im RejectedExecutionHandler?

Hier ist mein Code:

public static void main(String[] args) throws Exception{ 
    ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 1L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), 
      (Runnable r, ThreadPoolExecutor executor1) -> { 
       //TODO 
       //want to get the task name 
       System.out.println("in reject:"); 
    }); 
    Task t1 = new Task("t1"); 
    Task t2 = new Task("t2"); 
    Future<Integer> t1Fe = executor.submit(t1); 
    Future<Integer> t2Fe = executor.submit(t2); 

    System.out.println(t1Fe.get()); 
    System.out.println(t2Fe.get()); 
} 

static class Task implements Callable{ 
    private String name; 

    public Task(String name) { 
     this.name = name; 
    } 

    @Override 
    public Object call() throws Exception { 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     System.out.println(1); 
     return name; 
    } 
} 
+0

Ihre Aufgabe wird in eine FutureTask eingepackt, die keine Aufgabe für die Aufgabe bereitstellt. Sie können reflection verwenden, um auf das "callable" Feld der 'FutureTask' zuzugreifen, aber das ist kein sehr robuster Ansatz. – assylias

+0

Override RejectedExecutionHandler und erstellen Sie Ihre eigenen. Es ist der beste Weg. – canillas

+0

@canillas das ist, was in dem Code in der Frage getan wurde. Die Frage ist, wie man von der Runnable auf die zugrunde liegende Aufgabe zugreift. – assylias

Antwort

1

ich die submit Methode außer Kraft setzen und die FutureTask Klasse überschreiben!

public static void main(String[] args) throws Exception{ 
    ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 1L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), 
      (Runnable r, ThreadPoolExecutor executor1) -> { 
       //TODO 
       //want to get the task name 
       MyFutureTask task = (MyFutureTask)r; 
       System.out.println("in reject:"+task.name); 
    }); 
    Task t1 = new Task("t1"); 
    Task t2 = new Task("t2"); 
    Future<Integer> t1Fe = submit(executor,t1); 
    Future<Integer> t2Fe = submit(executor,t2); 

    System.out.println(t1Fe.get()); 
    System.out.println(t2Fe.get()); 
} 

public static Future submit(ThreadPoolExecutor executor,Callable task) { 
    if (task == null) throw new NullPointerException(); 
    MyFutureTask ftask = new MyFutureTask(task); 
    ftask.setName(((Task)task).name); 
    executor.execute(ftask); 
    return ftask; 
} 

static class MyFutureTask extends FutureTask{ 
    private String name; 
    public MyFutureTask(Callable callable) { 
     super(callable); 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 
static class Task implements Callable{ 
    private String name; 

    public Task(String name) { 
     this.name = name; 
    } 

    @Override 
    public Object call() throws Exception { 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     System.out.println(1); 
     return name; 
    } 
} 
+0

Schön gemacht - alternativ könnten Sie ThreadPoolExecutor erweitern und die 3 'submit' Methoden überschreiben. – assylias

+2

@assylias: besser, überschreiben ['newTaskFor'] (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/AbstractExecutorService.html#newTaskFo- java.util.concurrent.Callable -) was genau zu diesem Zweck gemacht wird; dann müssen Sie nicht alle "submit" -Methoden überschreiben oder befürchten, dass zukünftige Versionen zusätzliche Übermittlungsmethoden bieten, die Sie nicht außer Kraft gesetzt haben ... – Holger

Verwandte Themen