【问题标题】:Why I can't show my arrayList, when I saves her by another Thread?为什么我不能显示我的arrayList,当我用另一个线程保存她时?
【发布时间】:2019-12-05 21:54:41
【问题描述】:

您好,我在显示外部类的列表时遇到问题。我尝试使用 public void show() 方法,但列表为空。我认为问题出在线程上,这可能吗?谁能解释为什么会这样?

public class CollectionsOperation
{
    private List<Client> bufferedReaderClientLIst =
        Collections.synchronizedList(new ArrayList<Client>());

    BufferedReader bf = null;

    private static final String fileName = "clients.txt";

    public void bufferedReaderCollection()
        throws IOException
    {
        String line;
        try {
            bf = new BufferedReader(new InputStreamReader(
                new FileInputStream(fileName), "UTF-8"));

            while ((line = bf.readLine()) != null) {
                String[] split = line.split(";"); 
                String nameCompany = split[0].substring(2);
                String adress = split[1]; 
                String phoneNumber = split[2]; 
                String emailAdress = split[3];

                Client k = new Client(nameCompany, adress, phoneNumber, emailAdress);
                bufferedReaderClientLIst.add(k); 
            }
        } catch (IOException e) {
        }
    }

    public void runBufferedReader()
    {
        Thread t = new Thread(new CreateList());
        t.start();
    }

    public void show()
    {
        System.out.println(bufferedReaderClientLIst);
    }

    private class CreateList implements Runnable
    {
        @Override
        public void run()
        {
            CollectionsOperation o = new CollectionsOperation();
            try {
                o.bufferedReaderCollection();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

【问题讨论】:

  • 你永远不会打电话给o.show()
  • 我已经调用了另一个类:public static void main(String[] args) throws IOException { CollectionsOperation k = new CollectionsOperation(); k.runBufferedReader(); k.show();
  • 那么您应该更新问题的代码以匹配您尝试运行的代码。就目前而言,它们似乎有所不同。
  • 如果您在评论中输入的是您实际使用的,因为runBufferedReader 中的代码在单独的线程中运行,对k.show() 的调用可能发生在之前 您的列表已填充。

标签: java multithreading arraylist bufferedreader inner-classes


【解决方案1】:

问题只是你的方法CreateList::run 创建了一个CollectionsOperation 的新实例。因此,原始对象方法 show 不会访问与您的 CreateList 类填充的列表相同的数据。

相反,您可能想使用

        public void run()
        {
            CollectionsOperation.this.bufferedReaderCollection();
        }

替代方法是在 CreateList 中创建一个构造函数,并使用 CollectionsOperationobject 作为参数并使用它。

public class CollectionsOperation
{
    ...
    public void runBufferedReader()
    {
        Thread t = new Thread(new CreateList(this));
        t.start();
    }
    ...
    private class CreateList implements Runnable
    {
        CollectionsOperation co;
        public CreateList(CollectionsOperation co) {
            this.co = co;
        }

        @Override
        public void run()
        {
            try {
                co.bufferedReaderCollection();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

但您还应该查看线程同步,以便并发访问您的列表。

【讨论】:

  • 我已经尝试过您的解决方案,但效果始终是相同的空列表。控制台向我显示:[]。我为此 public void show() { synchronized(bufferedReaderClientLIst) { Iterator iterator = bufferedReaderClientLIst.iterator(); 更改了我的 show() 方法。 while (iterator.hasNext()) System.out.println(iterator.next()); } /* System.out.println(bufferedReaderClientLIst); */ } 但后来我什么也没收到
  • 我怀疑您可能需要进行一些同步 - 您的输出实际上等待输入完成。我在您发表的另一条评论中看到您在Thread.start() 之后直接有show() 不确定这是否是您代码的最终结构-那为什么要使用线程?如果不是,那么您是否想在列表仍在读取数据时显示列表的当前内容,或者只是在最后输出?例如,做其他事情,然后等待输入完成?
  • 感谢您的回答。我使用线程是因为我不希望错误加载数据影响用户界面的操作。我想将文件中下载的数据接收到arrayList中,然后通过添加其他方法来使用它们:排序,搜索等。我的问题是我无法使用数据,因为在线程中执行该方法后我丢失了访问它。我会尝试使用 CompletableFuture 在您看来这是解决此问题的好方法吗?
  • 我没有使用CompletableFuture 的经验,但我怀疑你会遇到类似的问题。我的建议是扩展您的 bufferedReaderCollection() 方法,使用您想要对数据执行的所有其他操作,然后从那里更新 GUI。如果您使用 swing-gui,请使用 SwingUtilities.invokeLater()
【解决方案2】:

这实际上取决于您何时以及如何开始致电o.show()。因为这个列表是可变的,并且是异步的。如果您确定在o.bufferedReaderCollection(); 之后调用o.show,它将显示预期值

-----------更新 --------------- 基本上下面的流程应该适合你。

Thread t = new Thread(new CreateList());
t.start();
try{
  t.join();
} catch (Exception e){
  e.printStackTrace();
}
System.out.println(bufferedReaderClientLIst);

【讨论】:

  • 我用过 k.runBufferedReader();然后 k.show();我的程序显示空列表 []。我想将文件的内容下载到 ArrayList,然后我想将此数据用于另一个函数。我使用 Thread,但无法完成列出。你有什么想法我可以做更多吗?
  • 您的场景是典型的“异步代码”问题。你的方法是错误的,因为当你使用t.start() 时你不能强制线程运行。一个丑陋的解决方法是您可以使用 Thread.join() 在打印之前等待该线程完成。另一种方法是使用`async-await。尽管 Java 语言不像 C# 或 JavaScript 那样提供此功能,但您可以从 this library 获得帮助。
猜你喜欢
  • 2014-05-07
  • 2022-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-03
  • 1970-01-01
  • 2011-01-30
  • 2023-03-23
相关资源
最近更新 更多