2013-09-22 164 views
0

我想執行一個執行多個後臺任務的後臺任務。我實際上想要做的是執行一個後臺進程,它爲列表中的每個對象執行一些代碼,並在固定線程池中執行它。因此,例如,我在列表中有100個用戶,並且我正在同時爲其中的每個用戶執行代碼,但同時不超過5個。javafx後臺任務:在另一個服務中調用服務

因此,我使用兩個服務/任務對:一個服務/任務在整個用戶列表上執行,此服務使用固定線程池作爲其執行程序併爲每個用戶執行一系列第二個服務/任務對在列表中。

像在下面的例子:

class MainService extends Service<List<User>> { 

    private List<User> users; 

    public MainService(List<User> users) { this.users=users; } 

    protected Task<List<User>> createTask(){ 
     return new MainTask(this.users) 
    } 
} 

class Maintask extends Task<List<User>> { 

    private List<User> users; 
    private Executor executor; 

    public MainTask(List<User> users) { 
     this.users=users; 
     this.executor=Executors.newFixedThreadPool(5); 
    } 

    protected List<User> call() throws Exception { 
     for (User user : this.users) { 
      System.out.println("Starting single service"); 
      SingleService service=new SingleService(user) 
      service.setExecutor(this.executor); 
      service.start(); 
      System.out.println("Single service started"); 
     } 
    } 
} 

class SingleService extends Service<User> { 

     private User user; 

     public SingleService(User user) { this.user=user; } 

     protected Task<User> createTask() { 
     return new SingleTask(this.user) 
     } 
} 

class SingleTask extends Task<User> { 

    private User user; 

    public SingleTask(User user) { this.user=user; } 

    protected User call() throws Exception() { 
     // Do some work 
    } 
} 

的代碼執行到的時刻時第一「開始單個服務」被打印,「單服務啓動」並沒有被打印在所有消息。據我看到SingleService已啓動,但它的createTask()根本沒有被執行。我在這裏犯了一些錯誤嗎?

回答

0

那麼,我想在不同的環境下做同樣的事情......從一個主要服務啓動多個服務。 我已經覆蓋服務的所有方法,這是我的打印輸出:

  • 服務只能從FX應用程序線程{從onFailed()方法}使用

服務不運行FX線程,但只能從FX線程調用。 因此,服務或任務中調用的所有服務和任務都不會執行。

這是我的解決方法:

public class FXComponentImporter extends Service<Void> implements JarImporter { 
    //Scanner<T> = Service<List<Class<T>>> 
    private Scanner<Node> nodeScanner = null; 
    private Scanner<Paint> paintScanner = null; 
    private Scanner<Animation> animationScanner = null; 

    private static int nodeCount = 0, paintCount = 0, animationCount = 0; 
    private final ObservableMap<String, Class<?>> foundComponents = FXCollections.observableHashMap(); 

    public FXComponentImporter() { 
     this(null); 
    } 

    public FXComponentImporter(File file) { 
     if (file != null) { 
      try { 
       this.nodeScanner = new Scanner<>(file, Node.class); 
       this.paintScanner = new Scanner<>(file, Paint.class); 
       this.animationScanner = new Scanner<>(file, Animation.class); 
      } catch (IOException ex) { 
       Logger.getLogger(FXComponentImporter.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } else { 
      File f = importJar(); 
      try { 
       this.nodeScanner = new Scanner<>(f, Node.class); 
       this.paintScanner = new Scanner<>(f, Paint.class); 
       this.animationScanner = new Scanner<>(f, Animation.class); 
      } catch (IOException ex) { 
       Logger.getLogger(FXComponentImporter.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
     this.scanningDone.bind(this.nodeScanningDone.and(this.paintScanningDone.and(this.animationScanningDone))); 

     this.scanningDone.addListener(new ChangeListener<Boolean>() { 
      @Override 
      public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { 
       if (newValue) { 
        if(scanningDone.isBound()){ 
         scanningDone.unbind(); 
        }      
        start(); 
        scanningDone.removeListener(this); 
       } 
      } 
     }); 

     startScanning(); 
    } 

    @Override 
    protected Task<Void> createTask() { 
     return new Task<Void>() { 
      @Override 
      protected Void call() throws Exception { 
       Map<String, Class<?>> map = new HashMap<>(); 
       List<Class<Node>> nodes = new ArrayList<>(); 
       List<Class<Paint>> paints = new ArrayList<>(); 
       List<Class<Animation>> anims = new ArrayList<>(); 

       CountDownLatch latch = new CountDownLatch(1); 
       //Platform needed due to Service only accessed from FX thread 
       Platform.runLater(() -> { 
        try { 
         //FX Stuff done here 
         nodes.addAll(nodeScanner.getMatchingClasses()); 
         paints.addAll(paintScanner.getMatchingClasses()); 
         anims.addAll(animationScanner.getMatchingClasses()); 

        } finally { 
         latch.countDown(); 
        } 
       }); 
       latch.await(); 

       this.updateMessage("Scanning for Nodes ... "); 
       nodes.stream().forEach(n -> { 
        if(n != null){ 
         map.putIfAbsent(n.getSimpleName(), n); 
        } 
        nodeCount++; 
       }); 
       this.updateMessage("Found : " + nodeCount + " Nodes ... "); 

       this.updateMessage("Scanning for Paints ... "); 
       paints.stream().forEach(p -> { 
        if(p != null){ 
         map.putIfAbsent(p.getSimpleName(), p); 
        } 
        paintCount++; 
       }); 
       this.updateMessage("Found : " + paintCount + " Paints ... "); 

       this.updateMessage("Scanning for Animations ... "); 
       anims.stream().forEach(a -> { 
        if(a != null){ 
         map.putIfAbsent(a.getSimpleName(), a); 
        } 
        animationCount++; 
       }); 
       this.updateMessage("Found : " + animationCount + " Animations ... "); 

       foundComponents.putAll(map); 

       return null; 
      } 
     }; 
    } 

    @Override 
    protected void executeTask(Task<Void> task) { 
     super.executeTask(task); 
     System.out.println(getClass().getSimpleName() + " is Executing " + task.getTitle()); 
    } 

    @Override 
    protected void cancelled() { 
     super.cancelled(); 
     System.out.println(getClass().getSimpleName() + " was Cancelled ... "); 
    } 

    @Override 
    protected void running() { 
     super.running(); 
     System.out.println(getClass().getSimpleName() + " is Running ... "); 
    } 

    @Override 
    protected void ready() { 
     super.ready(); 
     System.out.println(getClass().getSimpleName() + " is Ready! ... "); 
    } 

    @Override 
    protected void scheduled() { 
     super.scheduled(); 
     System.out.println(getClass().getSimpleName() + " is Scheduled ... "); 
    } 

    @Override 
    protected void failed() { 
     super.failed(); 
     System.out.println(getException().getMessage()); 
    } 

    @Override 
    protected void succeeded() { 
     super.succeeded(); 
     System.out.println("Importing Succeeded ... with: " + foundComponents.entrySet().size() + " results.\n"); 

     foundComponents.forEach((s, c) -> { 
      System.out.println(c.getSuperclass().getSimpleName() + " >> " + s + " : " + c.getSimpleName()); 
     }); 
    } 

    @Override 
    public void restart() { 
     super.restart(); 
     System.out.println(getClass().getSimpleName() + " is Restarting ... "); 
    } 




    private void startScanning() { 
     nodeScanner.stateProperty().addListener(nsl); 
     paintScanner.stateProperty().addListener(psl); 
     animationScanner.stateProperty().addListener(asl); 

     nodeScanner.start(); 
     paintScanner.start(); 
     animationScanner.start(); 
    } 

    private final BooleanProperty scanningDone = new SimpleBooleanProperty(false); 
    private final BooleanProperty nodeScanningDone = new SimpleBooleanProperty(false); 
    private final BooleanProperty paintScanningDone = new SimpleBooleanProperty(false); 
    private final BooleanProperty animationScanningDone = new SimpleBooleanProperty(false); 

    private final ChangeListener nsl = new ChangeListener<Worker.State>() { 
     @Override 
     public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) { 
      if (newValue.equals(State.SUCCEEDED)) { 
       nodeScanningDone.set(true); 
       nodeScanner.stateProperty().removeListener(this); 
      } 
     } 
    }; 
    private final ChangeListener psl = new ChangeListener<Worker.State>() { 
     @Override 
     public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) { 
      if (newValue.equals(State.SUCCEEDED)) { 
       paintScanningDone.set(true); 
       paintScanner.stateProperty().removeListener(this); 
      } 
     } 
    }; 
    private final ChangeListener asl = new ChangeListener<Worker.State>() { 
     @Override 
     public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) { 
      if (newValue.equals(State.SUCCEEDED)) { 
       animationScanningDone.set(true); 
       animationScanner.stateProperty().removeListener(this); 
      } 
     } 
    }; 


    public ObservableMap<String, Class<?>> getFoundComponents() { 
     return foundComponents; 
    }  
} 

和我的接口,如果你想嘗試一下:

public interface JarImporter { 
    public static File defaultDirectory = new File(System.getProperty("user.home")); 
    public static final FileChooser.ExtensionFilter classfilter = new FileChooser.ExtensionFilter("Jar files", "*.jar"); 

    static FileChooser defaultFileChooser(){ 
     FileChooser fc = new FileChooser(); 
     fc.getExtensionFilters().add(classfilter); 
     fc.setInitialDirectory(defaultDirectory); 
     return fc; 
    } 

    public default File importJar(){ 
     File jar = defaultFileChooser().showOpenDialog(null); 
     if(jar != null){ 
      return jar; 
     }else{ 
      return null; 
     } 
    } 
} 

希望這有助於..雖然只是看着問日期,並且是同時前...