-1

我正在使用一个应该在后台运行一些作业的程序。在应用程序关闭之前,它应该在实际关闭之前等待剩余的作业完成,所以我用一个静态数组列表创建了一个类来存储正在运行的线程,这样我就可以从我的应用程序的全局范围内访问所有这些作业并获得我想要的结果。

public class BackgroundWorker extends javax.swing.JDialog {
    private static ArrayList thlist;

    public static void DoThisThingAndDontBotherMe(Thread t) {
        thlist.add(t); // :3
        t.start();
    }

    public static void WaitForJobsToBeDone() {
        for(Object o : thlist.toArray()) {
            if(!((Thread) o).isAlive()) {
                thlist.remove(o);
            }
        }
        if(thlist.isEmpty())
            return;
        for(int i = 0; i < thlist.size(); i++) {
            try {
                ((Thread) thlist.get(i)).join();
            } catch(InterruptedException e) { System.err.println("Crap. A thread failed!! X.x");
        }
    }
}

...但是当我从外部类调用它时,像这样:

BackgroundWorker.DoThisThingAndDontBotherMe(new Thread() {
    System.out.println("HEY, im a creepy thread! But ill soon cause this program to throw a NullPointerExeption. And the lame programmer won't know why >:D");
});

程序在用 ':3' 注释的行中抛出一个空指针异常,就好像对 new Thread(){} 的调用是一个空指针 >.>

PS:如果我确实以这种方式创建了一个新的 Thread 变量,而不调用我的类然后调用它的 start() 方法,那么线程会按预期完成它的工作。但是我需要将这些线程存储在一个全局可访问的列表中,这样我就可以等待它完成,然后才能关闭我的应用程序。PS 2:上面的函数名称只是代表,并不是我在我的应用程序中使用的名称。我不对函数和类型使用长名称。

我没有考虑哪些静态/非静态规则?xx

4

5 回答 5

0

当你打电话时BackgroundWorker.DoThisThingAndDontBotherMe(new Thread()....,你确定你的ArrayList thlist; 已经初始化了吗?

于 2013-05-06T13:23:59.387 回答
0

你需要实例化thlist

private static ArrayList thlist = new ArrayList();

最好在这里使用泛型:

private static ArrayList<Thread> thlist = new ArrayList<>();

(如果您使用 Java 7)或:

private static ArrayList<Thread> thlist = new ArrayList<Thread>();

如果不。

于 2013-05-06T13:24:05.107 回答
0

你需要初始化你的列表:

ArrayList myList = new ArrayList();
于 2013-05-06T13:24:32.863 回答
0

您正在尝试重新发明一个ExecutorService.

您可以通过执行以下操作以更有效和惯用的方式解决问题(使用直接从 JavaDoc 页面获取的关闭方法):

public class BackgroundWorker extends javax.swing.JDialog
{
  private final ExecutorService _executorService = Executors.newFixedThreadPool(NUMBER_OF_CONCURRENT_OPERATIONS);

  public void doThisThingAndDontBotherMe(Runnable runnable)
  {
    _executorService.execute(runnable);
  }

  public void waitForJobsToBeDone()
  { 
    _executorService.shutdown();
    try 
    {
      // Wait a while for existing tasks to terminate
      if (!_executorService.awaitTermination(60, TimeUnit.SECONDS)) 
      {
        _executorService.shutdownNow(); // Cancel currently executing tasks
        // Wait a while for tasks to respond to being cancelled
        if (!_executorService.awaitTermination(60, TimeUnit.SECONDS))
          System.err.println("Pool did not terminate");
      }
    } 
    catch (InterruptedException ie) 
    {
      // (Re-)Cancel if current thread also interrupted
      _executorService.shutdownNow();
      // Preserve interrupt status
      Thread.currentThread().interrupt();
    }
  }
于 2013-05-06T13:24:56.050 回答
0

你忘了初始化

ArrayList list = new ArrayList();
于 2013-05-06T13:25:11.007 回答