为了账号安全,请及时绑定邮箱和手机立即绑定

在类构造函数中调用线程的替代方法

在类构造函数中调用线程的替代方法

慕工程0101907 2021-05-12 17:22:21
我有一个可以被多个线程访问的类。我希望该类在响应调用(getSomething)之前先做一些事情。我当时想开始在类构造函数中启动SampleThreadinside,但我不喜欢在构造函数中启动线程的想法。我正在考虑做这样的事情,但是我不确定这是否正确。将在类上调用getSomething的第一个线程将启动一个线程。但是我仍然不确定这是否正确。。我担心多个SampleThread会运行,而我只希望它运行一次。public class A{    private final AtomicBoolean isReady = new AtomicBoolean(false);    public A{    }    public void getSomething(){        if(!isReady.get()){            new SampleThread().start();        }        //continue with the rest of the method    }}public class SampleThread{    public void run(){        //Do some long running task once done        isReady.set(true);    }}我没有办法添加一个名为start()的方法,在该方法中我可以调用我的SampleThread,因为该方法是由框架调用的。有什么提示吗?
查看完整描述

1 回答

?
小唯快跑啊

TA贡献1863条经验 获得超2个赞

这种方式具有竞争条件:


public void getSomething(){

    if(!isReady.get()){

        new SampleThread().start();

    }

    //continue with the rest of the method

}

这是原子的: if(!isReady.get())但是与之关联的条件语句的主体不是:


{

    new SampleThread().start();

}

因此,您可以启动两次该线程。


同步逻辑可防止出现竞争情况。这也将增加对象上潜在的锁定数量,但是if(!isReady.get())应该快速执行,这应该是可以接受的。

请注意,AtomicBoolean如果布尔值仅在同步语句中使用,则可能不需要使用。


所以这里有两种方式可以根据您的要求。


1)为了getSomething()开始第一次调用,SampleThread 并且其他线程在执行之前等待初始化结束getSomething():


public void getSomething(){

    synchronized(this){

      // init the logic 

      if(!isReady){

          SampleThread t = new SampleThread();

          t.start(); 

          t.join();  // wait for the SampleThread thread termination

          isReady.set(true);           

      }         

      // execute the next only as the init thread was terminated

      if(isReady){

         //continue with the rest of the method

      }


    }     

}

2)为了让在第一次调用getSomething()开始SampleThread和别人线程不会等待此初始化执行前结束getSomething():


public void getSomething(){

    synchronized(this){

      // init the logic once

      if(!isReady.get()){

          SampleThread t = new SampleThread();

          t.start();                                   

      }                                   

    }

    //continue with the rest of the method       

}

并设置isReady以true在年底run()的SampleThread:


public void run(){

    //Do some long running task once done

    isReady.set(true);

}


查看完整回答
反对 回复 2021-05-26
  • 1 回答
  • 0 关注
  • 150 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信