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

标签 java multithreading javafx

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

我有一个需求,根据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/

相关文章:

java - volatile 关键字有什么用?

java - JMapViewer 是线程安全的吗?

css - 只显示左右边框

JavaFX应用程序: launching by double click?

JavaFX 属性 : Overriding getBean() method?

java - 振动直到按下按钮,当按钮未按下(或手指离开)时停止振动

java - java 中的简单计算器库(Android)

java - 无法获取 firebase 中除 null 之外的 child 值

java - 需要 AnnotationConfiguration 实例

c++ - 如何让 std::thread 停止?