天天看点

java中Atomic类之AtomicBooleanjava中Atomic类之AtomicBoolean类举例说明1、单线程2、多线程3、AtomicBoolean多线程

java中Atomic类之AtomicBoolean

在java.util.concurrent.atomic包下,有AtomicBoolean , AtomicInteger, AtomicLong, AtomicReference等类,它们的基本特性就是在多线程环境下,执行这些类实例包含的方法时,具有排他性,即当某个线程进入方法,执行其中的指令时,不会被其他线程打断,而别的线程就像自旋锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择一个另一个线程进入。

举例说明

以AtomicBoolean为例,单线程执行普通的方法(如下),不会出现线程问题:

1、单线程

package com.example.test;

/**
 * Created by PC on 2018/4/28.
 */

public class NormalBoolean implements Runnable{
    public static boolean exits = false;

    private String name;

    public NormalBoolean(String name){
        this.name = name;
    }


    @Override
    public void run() {
        if(!exits){
            exits = true;
            System.out.println(name + ",step 1");
            System.out.println(name + ",step 2");
            System.out.println(name + ",step 3");
            exits = false;
        } else {
            System.out.println(name + ",step else");
        }
    }

    public static void main(String[] args) {
        new NormalBoolean("张三").run();
    }
}
           

单线程结局

张三,step 
张三,step 
张三,step 
           

然而,当多线程执行时,就会出现在执行判断之后的命令时,会有其他线程插入,变更exits的值。如下段代码:

2、多线程

package com.example.test;

/**
 * Created by PC on 2018/4/28.
 */

public class NormalBoolean2 implements Runnable{


    private String name;

    public NormalBoolean2(String name) {
        this.name = name;
    }

    @Override
    public void run() {
         //如果exit为false
        if(!TestBoolean.exits){
            try {
                Thread.sleep();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TestBoolean.exits = true;

            System.out.println(name + ",step 1");

            System.out.println(name + ",step 2");


            System.out.println(name + ",step 3");
            TestBoolean.exits = false;

        } else {
            System.out.println(name + ",step else");
        }

    }
}
           

多线程启动

package com.example.test;

/**
 * Created by PC on 2018/4/28.
 */

public class TestBoolean {
    public  static boolean exits = false;
    public static void main(String[] args) {
    //在这里启动的时候,启动了4个线程,每一个线程启动前睡眠1秒钟,这样的话一个线程跑得快,就可能出现变更exits的值,从而走到else语句里。
     for(int i=;i<;i++){
             try {
                 Thread.sleep();
                 } catch (InterruptedException e) {
                 e.printStackTrace();
            }
       Thread thread = new Thread(new NormalBoolean2("李四"+i));
       thread.start();


        }
    }
}
           

多线程结局

线程0,跑得比较快,当他执行完TestBoolean.exits = true时,线程1正好走到 if(!TestBoolean.exits)的判断。这时候,if里面的判断语句为!TestBoolean.exits=false,于是线程1走进了else语句。这证明了多线程执行是不安全的。

李四,step 
李四,step else
李四,step 
李四,step 
李四,step 
李四,step 
李四,step 
李四,step 
李四,step 
李四,step 
           

现在,使用AtomicBoolean就可以确保多线程的情况下安全的运行,只有一个线程进行业务处理。

3、AtomicBoolean多线程

package com.example.test;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by PC on 2018/4/28.
 */

public class TestAtomicBoolean implements Runnable{

    //使用给定的初始值创建新的 AtomicBoolean。
    public static AtomicBoolean exits = new AtomicBoolean(false);
    private String name;

    public TestAtomicBoolean(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        //一般情况下,我们使用 AtomicBoolean 高效并发处理 “只初始化一次” 的功能要求:
        //如果当前状态值等于预期值,则以原子方式将同步状态设置为给定的更新值。
        //如果成功,则返回 true。返回 False 指示实际值与预期值不相等。
        //1.取得当前值
        //2.计算+1后的值
        //3.如果当前值还有效(没有被别的线程修改的话),设置那个+1后的值
        //4.如果设置没成功(当前值已经无效了即被别的线程改过了), 再从1开始.
        boolean curent=exits.get();//返回当前值。
         System.out.println(curent);
        //compareAndSet(预期值, 新值)
        if(exits.compareAndSet(false,true)){
            System.out.println(name + ",step 1");
            System.out.println(name + ",step 2");
            System.out.println(name + ",step 3");
        } else {
            System.out.println(name + ",step else");
        }

    }
}
           

AtomicBoolean多线程启动

package com.example.test;

/**
 * Created by PC on 2018/4/28.
 */

public class TestBoolean {
    public  static boolean exits = false;
    public static void main(String[] args) {

        for(int i=;i<;i++){
         try {
                Thread.sleep();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
      Thread thread = new Thread(new TestAtomicBoolean("张三"+i));
      thread.start();


       }
    }
}
           

AtomicBoolean多线程结局

线程0进来的时候,当前状态值(false)等于预期值(false),于是走if语句,并将当前状态值设置为给定的更新值(true)。从这以后,当前状态值(true)不等于预期值(false),于是永远走else()语句

false
张三,step 
张三,step 
张三,step 
true
张三,step else
true
张三,step else
true
张三,step else
true
张三,step else
true
张三,step else
true
张三,step else
true
张三,step else
true
张三,step else
true
张三,step else
           
注意:本文参考了https://blog.csdn.net/wo541075754/article/details/51509586,这篇博客写得很好,但是有很多问题,于是我呢修改了该博客。