gpt4 book ai didi

java - javafx多线程如何顺序执行?

转载 作者:行者123 更新时间:2023-12-02 01:27:21 24 4
gpt4 key购买 nike

不知道还有没有其他好的方法可以达到我想要的结果,谢谢。

我有一个需求,根据url,创建多个webview线程,并按顺序执行,比如线程执行完,然后触发线程二执行,以此类推,我使用的是synchronized(lobject)方法,但是在JAVAfx遇到问题,代码如下:

public class LockObject {

public int orderNum = 1;
public final static int MaxValue=9;

public LockObject(int orderNum){
this.orderNum = orderNum;
}
}


public class DownloadThread extends Thread{

private LockObject lobject;
private int printNum =0;
private String url;

public DownloadThread(LockObject lobject,int printNum,String url){
this.lobject=lobject;
this.printNum = printNum;
this.url = url;
}
@Override
public void run() {
synchronized(lobject){
while(lobject.orderNum <= lobject.MaxValue){
if(lobject.orderNum == printNum){
System.out.print(printNum);
Platform.runLater(new Runnable() {
@Override
public void run() {
webView.getEngine().load(url);
webView.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
@Override
public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) {
if (newValue == Worker.State.SUCCEEDED) {
try {
//xxxxx

// java.lang.IllegalMonitorStateException
lobject.notifyAll();
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
});
lobject.orderNum++;
if(lobject.orderNum==downloadThreads.length){
saveCsvFile(goodCSVS);
}
//lobject.notifyAll(); is ok
}else{
try {
lobject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}


通话地点


private DownloadThread[] downloadThreads;
LockObject lobject = new LockObject(1);
downloadThreads = new DownloadThread[tableView.getItems().size()];
for (int i = 0; i < tableView.getItems().size(); i++) {
UrlModel item = tableView.getItems().get(i);
downloadThreads[i] = new DownloadThread(lobject,tableView.getItems().size()-i,item.getLink());
downloadThreads[i].start();
}

在Platform.runLater中的run方法中调用lobject.notifyAll()会报IllegalMonitorStateException。地址处理完之后,我想唤醒下一个线程来执行。

最佳答案

如果需要按顺序执行多个任务,则无需创建多个线程。仅使用单个线程将保证下一个任务仅在前一个任务完成后执行。您还应该考虑使用 CountDownLatch而不是在对象上同步。

ExecutorService executor = Executors.newSingleThreadExecutor();
try {
for (UrlModel model : tableView.getItems()) {
executor.submit(() -> {
CountDownLatch latch = new CountDownLatch(1);
Platform.runLater(() -> {
engine.load(model.getLink())
engine.getLoadWorker().runningProperty().addListener((obs, ov, nv) -> {
if (!nv) {
latch.countDown();
}
});
});
latch.await();
// do whatever needs to happen after the WebEngine finishes loading
return null; // using #submit(Callable) and Callable needs to return something
});
}
} finally {
executor.shutdown();
}

一些注意事项:

  • 如果表没有要处理的项目,您可能希望避免创建 ExecutorService。也就是说,假设您不会每次都重用相同的 ExecutorService
  • 如果您重用ExecutorService,请不要调用shutdown()
  • ExecutorService 使用非守护线程。您可以通过提供创建守护线程的 ThreadFactory 来自定义它。
  • 我向 Worker#running 属性而不是 status 属性添加了一个监听器,以便更轻松地确保调用 countDown()无论负载的最终状态如何(即是否是 SUCCEEDEDCANCELLEDFAILED)。
  • 您可能希望在完成后删除添加到 Worker 属性的监听器。您可以通过使用匿名类(而不是我使用的 lambda 表达式)并在 changed 方法内调用 obs.removeListener(this) 来完成此操作,其中 obs ObservableValue 参数。

关于java - javafx多线程如何顺序执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56717080/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com