一、定义

Balking(犹豫)模式用在一个线程发现另一个线程或本线程已经做了某一件相同的事,那么本线程就无需再做,直接结束返回。
例如:

  1. public class MonitorService {
  2. //用来表示是否有线程已经执行启动
  3. private volatile boolean starting=false;
  4. public void start(){
  5. System.out.println("尝试启动监控线程");
  6. synchronized (this){
  7. if (starting){
  8. return;
  9. }
  10. //如果第一次访问,则令starting值为false,表示已经开始过。
  11. starting = true;
  12. }
  13. //真正启动监控线程...
  14. }
  15. }

编程的时候要考虑方法start的线程安全性,多个线程调用start方法对starting又读又写,所以要加上synchronzied块保证原子性。
这样当多个线程调用start方法时,获得锁的线程会将starting值改为真,其他线程阻塞住。当前线程将锁释放掉后,其它线程继续运行,但是starting值已经为真,直接返回,不再向下执行启动监控线程的代码。注意这里在starting上加上volatile是保证可见性,即一个线程改变变量值后,其余线程能够访问到最新值。

二、应用

Balking可用来实现线程安全的单例

  1. import com.sun.scenario.animation.shared.SingleLoopClipEnvelope;
  2. public class Singleton {
  3. //构造方法设置为private,类外部不可以new出对象
  4. private Singleton(){
  5. }
  6. private static Singleton INSTANCE = null;
  7. public static synchronized Singleton getINSTANCE(){
  8. if(INSTANCE!=null){
  9. return INSTANCE;
  10. }
  11. INSTANCE = new Singleton();
  12. return INSTANCE;
  13. }
  14. }

对getINSTANCE方法加锁,当不同线程调用getINSTANCE方法时,会对调用的对象上锁,第一个获取到锁的线程会创建实例并返回,其它阻塞住的线程再次获得锁时,会发现已经创建了一个实例,会将创建线程的引用返回,以保证多个线程共用一份实例。