【问题标题】:run method works but thread won't call itrun 方法有效,但线程不会调用它
【发布时间】:2014-12-11 03:57:12
【问题描述】:

我必须实现一个类来存储有关学校项目的机场信息。该课程应该从我们的讲师提供给我们的以 HTML 编写的网站中读取有关航班和乘客信息的数据,为了做到这一点,我们正在使用线程。我的问题是当我在我的线程上调用start()方法时,它不会调用我实现runnable的类上的run方法,这很奇怪,因为当我第一次测试程序并直接调用run()方法时,它工作得很好。这是我的工作类的 run 方法中的 while 循环,它执行实际的数据处理。

while (1 == 1) {
    temp = scan.next();
    if ((temp.equals("</body>")))
        break;
    else {
        name = temp;
        flightNum = scan.nextInt();
        city = scan.next();
        indexOfBR = city.indexOf("<");
        city = city.substring(0, indexOfBR);

        synchronized (airplanes) {
            addFlight(flightNum, city);
            addPassengerReservation(flightNum, name);
        }
    }
}
scan.close();

该循环应该读取乘客姓名,然后是航班号,然后是目的地城市,在 html 文件中存储为:

"passenger name" "flight Number" "destination city"<br>

创建和运行线程的方法是

public void readFlightData(String[] urls) {
    for (int x = 0; x < urls.length; x++) {
        if (!(urls[x].equals(""))) {
            try {
                Worker w = new Worker(new URL(urls[x]));
                Thread work = new Thread(w);
                work.start();
            }
            catch (MalformedURLException e) {
                //do nothing
            }
        }
    }
}

当我在工作线程上调用 start 时,此方法不会调用 run 方法,我不知道为什么。任何帮助将不胜感激

我发现问题出在 while 循环中的同步块中。传递给同步块飞机的对象是一个 ArrayList,用于保存 Airport 类中的航班和乘客信息。 addFlight() 方法旨在添加具有 flightNum 和目的地城市的航班。 addPassengerReservation 将一名乘客添加到指定的航班号,名为“name”

【问题讨论】:

  • work = new Thread(w); 行真的在运行吗?也许你应该记录那个MalformedURLException,这样你就知道它已经发生了。
  • 我回去做了。线程正在运行。或者至少,代码没有抛出 MalformedURLException。此外,当我通过直接调用 w.run() 运行代码时,它起作用了,我现在使用的 URL 与我当时使用的 URL 相同
  • 只是告诉你,尽管while(1 == 1)你也可以直接写while(true)来创建一个无限循环。
  • 我刚刚在工作中调用了isAlive,线程实际上还活着。是实际课堂作业中的编码问题吗?我很困惑
  • 听起来你需要开始使用你的调试器了。

标签: java


【解决方案1】:

代码非常脆弱。我建议进行以下更改。我认为有一个 MalformedURLException 并且您正在隐藏它。

public void readFlightData(String[] urls) {
    for (int x = 0; x < urls.length; x++) {
        if (!(urls[x].equals(""))) {
            try {
                Worker w = new Worker(new URL(urls[x]));
                Thread work = new Thread(w);
                work.start();
            }
            catch (MalformedURLException e) {
                System.err.print(e);
            }
        }
    }
}

【讨论】:

  • 我进行了这些更改,代码没有抛出错误,但是仍然无法正常工作。 start 方法在调用实例化线程的对象的 run 方法之前究竟发生了什么?也许这可能会导致问题。
  • 代替多个 url,您可以尝试为一个 url 运行一个线程吗?这将类似于您的单次执行。
  • 这就是我现在测试它的方式。 urls[] 只有一个元素
  • 只是为了测试,你可以注释掉你的run方法中的所有代码,然后放一个简单的System.out语句,看看是否有效?另一件事就是注释掉同步块,看看是否有效
  • 我添加了system.out语句,发现while循环中的同步块有问题。它到达同步块,但由于某种原因,该块中的方法调用不会修改当前对象。
【解决方案2】:

我想通了。我的问题是,在我的 Airport 类完成运行我创建的线程并下载必要的信息之前,我正在调用它的方法。我不得不在所有线程上调用 join() 来解决这个问题。对于那些好奇的人,这里是工作代码:

ArrayList<Thread> threads = new ArrayList<Thread>();
int x;

for (x = 0; x < urls.length; x++) {
    if (!(urls[x].equals(""))) {
        try {
            Worker w = new Worker(new URL(urls[x]));
            Thread work = new Thread(w);
            work.start();
            threads.add(work);
        }
        catch (MalformedURLException e) {
            System.err.print(e);
        }
    }
}

for (x = 0; x < threads.size(); x++)
    try {
        threads.get(x).join();
    } catch (InterruptedException e) {
        e.printStackTrace();
}

【讨论】:

  • 恭喜您自己解决了问题。但是与run() 相关的join 怎么没有被调用呢?顺便提一句。您应该通过重新设置线程上的中断标志或抛出 InterruptedException 来修复InterruptedException 的处理。 “Brian Goetz”描述了处理 InterruptedExceptions 的策略,甚至在这篇博客文章中描述了 Java theory and practice: Dealing with InterruptedException
  • 原来线程实际上正在调用运行,但是,我只是通过我的测试没有意识到这一点,因为我调用的 Junit 测试在我创建的线程完成下载所有之前完成运行必要的信息。这导致了昨天困扰我的错误。通过在创建线程的方法中调用 join,我有效地阻止了该方法结束,并停止运行 Junit 测试,直到所有线程都完成了它们的信息下载。
猜你喜欢
  • 2014-12-25
  • 2017-01-19
  • 1970-01-01
  • 2015-03-31
  • 1970-01-01
  • 1970-01-01
  • 2011-03-03
  • 2021-08-12
  • 1970-01-01
相关资源
最近更新 更多