首页 \ 问答 \ JavaFX的。(JavaFX. Adding items to the list in different threads is not working)

JavaFX的。(JavaFX. Adding items to the list in different threads is not working)

我有2节课。 头等舱是控制器 。 当您单击enter按钮时,在集合中添加许多不同线程中的对象,并在循环在10次迭代后退出时将此集合显示为控制器的类。

public class Controller {
    private int count = 3;

    @FXML
    private Button enter;

    @FXML
    public void getData() throws IOException{
        //Create collection
        List<String> synchList = Collections.synchronizedList(new ArrayList<String>());

        ExecutorService executor = Executors.newFixedThreadPool(count);

        for (int i=0; i<10; i++) {

            Runnable myThread= new MyThread(synchList); 
            executor.execute(myThread);

        }

        executor.shutdown();

        System.out.println(synchList); //Show collection
}

第二类是MyThread 。 它执行一些任务。 收到的对象早期存储在集合中(例如,延迟添加3个对象,模拟某些任务的性能)

public class MyThread implements Runnable{
    public List<String> list = null; 

    public MyThread(List<String> list){
        this.list = list;   
    }

    @Override
    public void run() {
        try {
            Thread.sleep(2000);
            list.add("Object2");
            Thread.sleep(2000);
            list.add("Object3");
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

在代码执行结束时,我得到一个空列表 。 请告诉我我做错了什么以及如何解决这个问题? 谢谢!


I have 2 class. First class is controller. When you click on the enter button, in the collection adding many objects in different threads and presented this collection as the class of the controller when the loop exits after 10 iterations.

public class Controller {
    private int count = 3;

    @FXML
    private Button enter;

    @FXML
    public void getData() throws IOException{
        //Create collection
        List<String> synchList = Collections.synchronizedList(new ArrayList<String>());

        ExecutorService executor = Executors.newFixedThreadPool(count);

        for (int i=0; i<10; i++) {

            Runnable myThread= new MyThread(synchList); 
            executor.execute(myThread);

        }

        executor.shutdown();

        System.out.println(synchList); //Show collection
}

The second class is MyThread. It performs some task. The received object is stored in collection early (for example, add 3 of the object with a delay, simulating the performance of some task)

public class MyThread implements Runnable{
    public List<String> list = null; 

    public MyThread(List<String> list){
        this.list = list;   
    }

    @Override
    public void run() {
        try {
            Thread.sleep(2000);
            list.add("Object2");
            Thread.sleep(2000);
            list.add("Object3");
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

At the end of the code execution, I get an empty list. Please tell me what am I doing wrong and how to fix this situation? Thank you!


原文:https://stackoverflow.com/questions/40767895
更新时间:2019-07-12 10:31

最满意答案

看一下ExecutorService.shutdown的文档:

启动有序关闭,其中先前提交的任务将被执行,但不会接受任何新任务。 如果已经关闭,调用没有其他影响。

此方法不会等待先前提交的任务完成执行。

使用shutdown仅阻止提交新任务。 它不能确保所有任务都完成。

相反,您可以使用awaitTermination来实现所需的效果:

executor.shutdown();

while (true) {
    try {
        if (executor.awaitTermination(1, TimeUnit.HOURS)) {
            break;
        }
    } catch (InterruptedException ex) {
    }
}

System.out.println(synchList); //Show collection

但是,您应该确保代码不是从应用程序线程运行,否则GUI会变得无响应...

更新

如果您希望按顺序添加结果,使用MyThread实现Callback<List<String>>并使用结果将是更好的选项,因为这允许您从任务(最终列表的子列表)中检索结果并组合结果到一个列表:

public class MyThread implements Callable<List<String>> {

    @Override
    public List<String> call() throws Exception {
        List<String> list = new ArrayList(2);
        Thread.sleep(2000);
        list.add("Object2");
        Thread.sleep(2000);
        list.add("Object3");
        Thread.sleep(2000);
        return list;
    }
}
//Create collection
List<String> resultList = new ArrayList<>();

ExecutorService executor = Executors.newFixedThreadPool(count);

Callable<List<String>>[] tasks = new Callable[10];
for (int i = 0; i < tasks.length; i++) {
    tasks[i] = new MyThread();
}

List<Future<List<String>>> futures = executor.invokeAll(Arrays.asList(tasks));
executor.shutdown();

for (Future<List<String>> future : futures) {
    // combine results
    resultList.addAll(future.get());
}

System.out.println(resultList); //Show collection

Take a look at the documentation of ExecutorService.shutdown:

Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.

This method does not wait for previously submitted tasks to complete execution.

Using shutdown only prevents new tasks from being submitted. It does not make sure all tasks are finished.

Instead you could use awaitTermination to achieve the desired effect:

executor.shutdown();

while (true) {
    try {
        if (executor.awaitTermination(1, TimeUnit.HOURS)) {
            break;
        }
    } catch (InterruptedException ex) {
    }
}

System.out.println(synchList); //Show collection

You should however make sure the code isn't run from the application thread, since otherwise the GUI becomes unresponsive...

Update

In case you want the results to be added sequentially, implementing Callback<List<String>> with MyThread and using the results would be the better option, since this allows you to retrieve results from the tasks (sublists of the final list) and combine the results to a single list:

public class MyThread implements Callable<List<String>> {

    @Override
    public List<String> call() throws Exception {
        List<String> list = new ArrayList(2);
        Thread.sleep(2000);
        list.add("Object2");
        Thread.sleep(2000);
        list.add("Object3");
        Thread.sleep(2000);
        return list;
    }
}
//Create collection
List<String> resultList = new ArrayList<>();

ExecutorService executor = Executors.newFixedThreadPool(count);

Callable<List<String>>[] tasks = new Callable[10];
for (int i = 0; i < tasks.length; i++) {
    tasks[i] = new MyThread();
}

List<Future<List<String>>> futures = executor.invokeAll(Arrays.asList(tasks));
executor.shutdown();

for (Future<List<String>> future : futures) {
    // combine results
    resultList.addAll(future.get());
}

System.out.println(resultList); //Show collection
2016-11-23

相关问答

更多

javafx:绑定不按预期工作(javafx: Bindings not working as expected)

你有一个ObservableList<Trade> ,其中每个Trade对象都有一个可观察的totalProperty() 。 当该列表的内容发生更改或者属于任何元素的任何单个totalProperty()更改时,您的sumOfTotals需要更新。 你可以手工做到这一点: DoubleBinding sumOfTotalsBinding = new DoubleBinding() { { bind(observableListOfTrades); obs ...

使用Python 2.7中的线程将项添加到列表中(Adding items to a list using threads in Python 2.7)

最明智的做法是假设操作不是线程安全的,除非你毫无疑问地知道它们是什么。 确保任何操作的原子性的最简单方法是在执行操作之前获取锁定,并且仅在执行操作时释放它。 现在, with语句非常简单,因为锁定对象是上下文管理器。 假设您的列表是模块全局my_list那么这很容易实现如下。 my_lock = threading.Lock() my_list = [] : : : def my_list_append(o): with my_lock: my_li ...

在单个TableView中显示不同的ObservableList [JavaFX](Displaying different ObservableList in a single TableView [JavaFX])

出了什么问题 摆脱displayList,TableView已经引用了它显示的项目列表,所以只需将其设置为适当的列表即可。 目前,您的显示列表值与基础数据值不同步。 假设 我假设您的TableView采用StoredItem类型的项目,并且PipeCable和Element也是StoredItem类型(尽管继承或接口实现)。 如何解决它 通常,您可以这样做: tableView.setItems(data.getPipeCableList()) 并且在选择时适当地选择元素列表。 但由于Java ...

JavaFX中的自动完成组合框(AutoComplete ComboBox in JavaFX)

首先,你必须在你的项目中创建这个类: import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.EventHandler; import javafx.scene.control.ComboBox; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; publi ...

Javafx 8 - setVisible()被阻止(Javafx 8 - setVisible() is blocked)

在用户kleopatra在评论中的一些帮助中,我来自oracle的以下链接: https://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm 基本上我的问题总结如下: JavaFX场景图表示JavaFX应用程序的图形用户界面,它不是线程安全的,只能从UI线程(也称为JavaFX Application线程)访问和修改。 在JavaFX Application线程上实现长时间运行的任务不可避免地使应用程序UI无响应 。 最佳实践是在一个或多个后 ...

JavaFX中的工具提示不起作用?(Tooltip in JavaFX not working?)

如果有其他人想知道的原因是因为我使用了Cyborg的RAT 7鼠标。 没有Cyborg的软件,mac出于某种原因认为鼠标在不断移动。 安装软件后,工具提示显示。 The reason for this if anyone else wonder is because I used a RAT 7 mouse by Cyborg. Without the software from Cyborg, the mac for some reason thought that the mouse was ...

使用Database JavaFX中的数据填充TableView(Populating a TableView with data from Database JavaFX)

您的代码中似乎存在许多错误。 首先,你将artistTable static 。 不要这样做 - 根本没有意义, FXMLLoader不会注入静态字段。 这就是你得到空指针异常的原因。 其次,传递给PropertyValueFactory (“Artist”)的值与模型类Artist中的任何属性的名称不匹配。 (即没有ArtistProperty()方法,也没有getArtist()方法)。 你可能想要 artistName.setCellValueFactory( new Pro ...

JavaFX 8:通过class.getResource()添加自定义CSS文件错误(JavaFX 8: Adding a Custom CSS File Via class.getResource() Error)

您没有Login类...您只有一个sample.Main类,因此代码中的Login.class引用将无法解析(该错误与CSS无关)。 一旦修复了类引用错误,您还需要修复对css文件位置的引用(因为您的Login.css文件不在示例包中,而是在源根目录中,因此它最终将被复制到你的类路径的根)。 要引用类路径根目录中的资源,请在/添加资源名称,即/Login.css 。 因此,在完成这些更改后,您将获得以下代码(您在先前的评论中验证了这些代码): scene.getStylesheets().add( ...

相关文章

更多

最新问答

更多
  • Unity着色器错误;(Unity shader error; presumably in if statement)
  • 如何在Liferay portlet中设置Cookie?(How to set a Cookie in Liferay portlet?)
  • C#只读访问List <>或其他集合,或ToArray()魔术(C# readonly access to List<> or other collection, or ToArray() magic)
  • 如何使用Google Web工具包创建登录应用程序?(How to create a login application using Google web tool kit? [closed])
  • 如何使我的函数返回结果作为全局变量?(How to make my function return results as a global variable?)
  • 为什么我的网站需要“启用32位应用程序”?(Why does my website need “Enable 32-bit applications”?)
  • 红宝石数组具有相同的值(ruby array of hash with same value)
  • Android(在Scala中):StackOverflowError取决于何时启动线程?(Android (in Scala): StackOverflowError depends on when to start a thread?)
  • 适用于iOS应用的通用链接(Universal Links for iOS apps)
  • 创建并打开文件linux编程(create and open file linux programming)
  • Datepicker,第2个日期是从第1个日期开始的X天(Datepicker, 2nd date is X days from 1st date)
  • 背景大小过渡不起作用(Transition on background-size doesn't work)
  • 在React / Redux中的On Click函数中传递Prop(Passing a Prop in an On Click Function in React/Redux)
  • 关键字在代码中做了什么,是否有没有此关键字的替代方法?(what does the keyword this does in the code and are there any alternate methods without this keyword? [duplicate])
  • 反向设计FoxPro / dBsae数据库以创建EER模型(Reverse Engineer a FoxPro/dBsae database to create the EER model)
  • 在R中的变量中组合具有相同值的行(Combine rows that have same value in a variable in R [duplicate])
  • SQL Server:非空唯一主键(SQL Server: Non-null unique vs. Primary Key)
  • 将扩展ASCII字符代码转换为ISO-8859-1(Convert extended ASCII character codes to ISO-8859-1)
  • 如何在.NET中读取m4a文件中的标签?(How to read tags out of m4a files in .NET?)
  • 呼叫链接的性能提升?(Performance gain on call chaining?)
  • 风景名胜区规划设计文本里面都包含哪些内容?推荐一家旅游规划设计公司?谢谢!
  • 如何在String中将字符串转换为枚举?(How do I convert a string to enum in TypeScript?)
  • SQLite SELECT出现异常如何解决它?(SQLite SELECT gives exception How to fix it?)
  • NSLog不会从ViewController类输出,而是来自AppDelegate类的WILL。(NSLog will NOT output from the ViewController class, but WILL from the AppDelegate class. iOS:Objective C)
  • 更改UIPicker突出显示的标签宽度(change UIPicker highlighted tab width)
  • 空心倒五角形(Hollow inverted pentagon)
  • 如何设置仅使用OpenID的Plone站点(How to setup Plone sites working only with OpenID)
  • Paperclip缺少Amazon S3的协议(https)(Paperclip is missing the Protocol (https) with Amazon S3)
  • 从宏中部署netbeans中的ANT文件(Deploy ANT file in netbeans from macro)
  • XMLReader是未知的(XMLReader is unknown)