美文网首页
多线程:原子类

多线程:原子类

作者: JBryan | 来源:发表于2020-02-01 13:26 被阅读0次
1.什么是原子类

原子类:一度认为原子是不可分割的最小单位,故原子类可以认为其操作都是不可分割。
对多线程访问同一个变量,我们需要加锁,而锁是比较消耗性能的,JDk1.5之后,​ 新增的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式,​ 这些类同样位于JUC包下的atomic包下,发展到JDk1.8,该包下共有17个类,​ 囊括了原子更新基本类型、原子更新数组、原子更新属性、原子更新引用。
1.8新增的原子类:DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder、Striped64

2.原子更新基本类型

大致可以归为3类:
AtomicBoolean、AtomicInteger、AtomicLong 元老级的原子更新,方法几乎一模一样​。
DoubleAdder、LongAdder 对Double、Long的原子更新性能进行优化提升​ 。
DoubleAccumulator、LongAccumulator 支持自定义运算。
AtomicInteger使用

package com.ljessie.sinopsis.atomic;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 原子的Integer型
 * @author zbw
 *
 */
public class AtomicIntegerDemo {
    
    private static AtomicInteger num = new AtomicInteger(0);
    
    public static void increate() {
        num.incrementAndGet();
    }
    
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread() {
                public void run() {
                    for (int j = 0; j < 10; j++) {
                        try {
                            increate();
                            System.out.println(num);
                            Thread.sleep(200);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        
                    }
                }
            }.start();
        }
    }
}

LongAccumulator 使用

package com.ljessie.sinopsis.atomic;

import java.util.concurrent.atomic.LongAccumulator;
import java.util.function.LongBinaryOperator;

/**
 * JDK1.8之后的原子Long型
 * @author zbw
 *
 */
public class LongAccumlatorDemo {

    public static void main(String[] args) {
        //输入一个数字,如果比上一个输入的大,则直接返回,如果输入的小,则返回上一个.
        LongAccumulator la = new LongAccumulator(new LongBinaryOperator() {
            
            @Override
            public long applyAsLong(long left, long right) {
                
                return left>right?left:right;
            }
        }, 5);
        
        la.accumulate(3);
        System.out.println(la.get());
        la.accumulate(7);
        System.out.println(la.get());
    }
}
3.原子更新数组类型

AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray,使用方法类似
AtomicIntegerArray使用

package com.ljessie.sinopsis.atomic;

import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.function.IntBinaryOperator;

/**
 * 原子的更新数组
 * @author zbw
 *
 */
public class AtomicIntegerArrayDemo {
    
    public static void main(String[] args) {
        int[] arr = {1,3,5,7,9};
        AtomicIntegerArray array = new AtomicIntegerArray(arr);
        int i = array.addAndGet(0, 3);
        System.out.println(i);
        
        int j = array.accumulateAndGet(4, 10, new IntBinaryOperator() {
            
            @Override
            public int applyAsInt(int left, int right) {
                //将10和数组下标为4的值进行对比,a[4]是left,10是right
                return left>right?left:right;
            }
        });
        
        System.out.println(j);
    }

}

4.原子更新属性
原子地更新某个类里的某个字段时,就需要使用原子更新字段类,Atomic包提供了以下4个类进行原子字段更新​ AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReference、AtomicReferenceFieldUpdater

package com.ljessie.sinopsis.atomic;

import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

/**
 * 原子属性
 * @author zbw
 *
 */
public class AtomicLongFieldUpdaterDemo {
    
    
    public static void main(String[] args) {
        AtomicLongFieldUpdater<Student> updater = AtomicLongFieldUpdater.newUpdater(Student.class, "id");
        
        Student student = new Student(1, "zbw");
        updater.compareAndSet(student, 1, 1000);
        System.out.println(student.getId());
        
        AtomicReferenceFieldUpdater<Student , String> referenceUpdater = 
                AtomicReferenceFieldUpdater.newUpdater(Student.class, String.class, "name");
        boolean isSuccess = referenceUpdater.compareAndSet(student, "zbw", "jessie");
        if(isSuccess) {
            System.out.println(student.getName());
        }
    }
    
    
}
class Student{
    volatile long id;
    volatile String name;
    public Student(long id,String name){
        this.id = id;
        this.name = name;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }   
}

使用上述类的时候,必须遵循以下原则
字段必须是volatile类型的,在线程之间共享变量时保证立即可见
字段的描述类型是与调用者与操作对象字段的关系一致。
也就是说调用者能够直接操作对象字段,那么就可以反射进行原子操作。
对于父类的字段,子类是不能直接操作的,尽管子类可以访问父类的字段。
只能是实例变量,不能是类变量,也就是说不能加static关键字。
只能是可修改变量,不能使final变量,因为final的语义就是不可修改。
对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段,不能修改其包装类型(Integer/Long)。
如果要修改包装类型就需要使用AtomicReferenceFieldUpdater。

5.原子更新引用

AtomicReference的使用

package com.ljessie.sinopsis.atomic;

import java.util.concurrent.atomic.AtomicReference;

/**
 * 原子的引用修改
 * @author zbw
 *
 */
public class AtomicReferenceDemo {

    
    public static void main(String[] args) {
        AtomicReference<Students> reference = new AtomicReference<Students>();
        Students student1 = new Students(1, "zbw");
        Students student2 = new Students(2, "jessie");
        reference.set(student1);
        reference.compareAndSet(student1, student2);
        Students student3 = reference.get();
        System.out.println(student3.getName());
    }
}

class Students{
    private long id;
    private String name;
    public Students(long id,String name){
        this.id = id;
        this.name = name;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
}

相关文章

  • 多线程

    9.1java多线程的实现继承Tread类Thread 为Runnable 的子类,子类为多线程操作类,必须覆写r...

  • 【Java】【Thread多线程】概述

    多线程概述 通过子类继承开启多线程public class Demo { public static voi...

  • 多线程:原子类

    1.什么是原子类 原子类:一度认为原子是不可分割的最小单位,故原子类可以认为其操作都是不可分割。对多线程访问同一个...

  • Java 多线程与锁的运用

    Java 多线程主要是实现方式有: 1.Thread 子类继承Thread,成为Thread的子类,调用start...

  • Java锁机制

    Java多线程编程的入门篇,主要介绍volatile修饰词、Synchronized以及Lock及其子类 多线程编...

  • 原子类型与原子操作

    原子类型和原子操作 并行编程、多线程与C++11 常见的并行编程有多种模型:共享内存、多线程、消息传递等。 多线程...

  • java线程&和各种奇奇怪怪的锁

    1、Java线程 一、Java多线程常用的两种实现方法 1、 继承Thread类 子类继承Thread类具备多线程...

  • 多线程6原子类

    代码

  • iOS开发之多线程(一)

    目录 概要 NSThread GCD NSOperation 多线程与锁 1.概要 进程 线程 多线程 多线程的原...

  • python——多线程

    多线程-threading 子类完成创建多线程 线程的执行顺序也是主线程和各个子线程随机执行,顺序不确定 线程对全...

网友评论

      本文标题:多线程:原子类

      本文链接:https://www.haomeiwen.com/subject/lcotxhtx.html