非静态线程作为静态函数的arg抛出NullPointerException

时间:2013-05-06 13:21:29

标签: java multithreading static arraylist

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

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'注释的行中抛出一个空指针异常,好像对新Thread(){}的调用是一个空指针&gt;。&gt;

PS:如果我以这种方式创建一个新的Thread变量,而不调用我的类然后调用它的start()方法,则该线程按预期完成其工作。但我需要将这些线程存储在全局可访问的列表中,以便在关闭应用程序之前等待它完成。 PS 2:上面的函数名称只是代表性的,不是我在我的应用程序中使用的名称。我不使用长名称来表示函数和类型。

我没有考虑哪种静态/非静态规则? x.x中

5 个答案:

答案 0 :(得分:0)

当您致电BackgroundWorker.DoThisThingAndDontBotherMe(new Thread()....时,您确定ArrayList thlist;已初始化了吗?

答案 1 :(得分: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>();

如果没有。

答案 2 :(得分:0)

您需要初始化列表:

ArrayList myList = new ArrayList();

答案 3 :(得分:0)

您正在尝试重新发明ExecutorService

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

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();
    }
  }

答案 4 :(得分:0)

你忘了初始化

ArrayList list = new ArrayList();