我想执行执行多个后台任务的后台任务。我实际上要做的是执行一个后台进程,为列表中的每个Object执行一些代码,并在固定的线程池中执行。因此,例如,我在列表中有100个用户,我同时执行每个用户的代码,但同时不超过5个。
因此我使用两个服务/任务对:一个服务/任务用于在整个用户列表上执行,该服务使用固定线程池作为其执行者,并为每个用户执行一系列第二服务/任务对清单。
如下例所示:
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 :(得分:0)
好吧,我正在尝试在不同的环境中做同样的事情......从单个主服务启动多个服务。 我已经覆盖了所有服务方法,这是我的打印输出:
服务不在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;
}
}
}
希望这会有所帮助..虽然只是看了问题日期,但是不久前......