将线程引用作为类级别属性?

时间:2010-11-11 20:22:50

标签: java multithreading thread-safety

我有一种情况需要从A调用B类中的method1()。当调用method1()时,它会创建一个新的Thread(MyThread)并立即启动它。在我的情况下,我从应用程序中的两个不同位置调用method1()。我不想每次都创建这个线程的新实例。在method1()里面,我尝试在创建一个新的MyThread实例之前检查myThread.isAlive()。但我得到一个编译错误MyThread需要初始化以调用MyThread.isAlive()。因此,如果放入Thread类型的方法属性,即

()的方法    {     线程myThread;     如果(myThread.isAlive())     {return};     .....    }

在MythB中为classB声明一个类级别属性并将其初始化为null是一个好主意。然后在method1()内部检查线程的状态,如果没有运行则创建一个新的?

class B()
{
   Thread myThread = null;
   public static B getInstance()
   {
       return B singleton object;
   }

   public void method1()
   {
     if(myThread.isAlive())
        return;
     myThread = new Thread(new Runnable(){
       public void run(){ 
              do some stuff.....
       }).start();
}

==================

class A()
{
  B.getInstance().method1();
}

==================

class someOtherClass()
{
  B.getInstance().method1();
}

3 个答案:

答案 0 :(得分:0)

当您第一次调用 method1 时,此代码将导致NullPointerException(NPE)被抛出,因为它将尝试在isAlive()上调用null 。您需要if(myThread != null && myThread.isAlive())

答案 1 :(得分:0)

使用Executor,特别是fixed thread pool,您可以做得更好。在B的构造函数中创建线程池并保留对它的私有最终引用。然后在method1()中提交Runnables,不要启动新线程。

这种方法有几个好处:Executor为您正确处理线程生命周期问题,您可以更改线程模型,以便非常轻松地增加线程,并且没有任何竞争条件(在线程初始化代码中 - 感谢评论者指出这一点)。您正在使用的Runnable中可能存在竞争条件。

编辑添加示例:

   class B()
   {
   private final Executor threadPool = Executors.newFixedThreadPool(1);
   private boolean taskSubmmitted = false;
   public static B getInstance()
   {
       return B singleton object;
   }

   public synchronized void method1()
   {
     if(taskSubmitted)
        return;
     myRunnable = new Runnable(){
       public void run(){ 
              do some stuff.....
       }};
     threadPool.submit(myRunnable);
     taskSubmitted = true;
   }

答案 2 :(得分:0)

class B()
{
          // class level variable works fine.... I dont see a problem 
  private Thread myThread = null;   

  public static B getInstance()
  {
    return B singleton object;
  }

  public void method1()
  {
     if(myThread != null && myThread.isAlive())
        return;

     myThread = new Thread(new Runnable(){        
      public void run(){ 
          do some stuff.....
      }).start();
   }
}