原子性操作,即为最小的操作单元,比如i=1,就是一个原子性操作,这个过程只涉及一个赋值操作。多线程原子性操作依赖在J.U.C包下的atomic系列的类。它主要包括四类:基本类型,数组类型,属性原子修改器类型,引用类型。
1.基本类型的实现:
package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicTest {
private static final AtomicInteger at=new AtomicInteger();
private static final ExecutorService es=Executors.newFixedThreadPool(20);
public static void main(String[] args) {
// TODO Auto-generated method stub
long start=System.currentTimeMillis();
for(int i=0;i<1000;i++)
{
Thread t1=new Thread() {
public void run()
{
System.out.println(Thread.currentThread().getName()+"实现了一次自增原子操作,结果为:"+at.incrementAndGet());
}
};
es.execute(t1);
}
try
{
Thread.sleep(5000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println("计算过程的耗时为:"+(System.currentTimeMillis()-start-5000));
System.out.println("累加1000次,得到结果"+at);
}
}
运行结果如下:
pool-1-thread-13实现了一次自增原子操作,结果为:984
pool-1-thread-8实现了一次自增原子操作,结果为:983
pool-1-thread-14实现了一次自增原子操作,结果为:982
pool-1-thread-20实现了一次自增原子操作,结果为:981
pool-1-thread-10实现了一次自增原子操作,结果为:980
pool-1-thread-12实现了一次自增原子操作,结果为:979
pool-1-thread-3实现了一次自增原子操作,结果为:978
pool-1-thread-7实现了一次自增原子操作,结果为:977
pool-1-thread-4实现了一次自增原子操作,结果为:976
pool-1-thread-18实现了一次自增原子操作,结果为:1000
pool-1-thread-9实现了一次自增原子操作,结果为:999
pool-1-thread-17实现了一次自增原子操作,结果为:998
pool-1-thread-6实现了一次自增原子操作,结果为:997
pool-1-thread-5实现了一次自增原子操作,结果为:996
pool-1-thread-2实现了一次自增原子操作,结果为:995
计算过程的耗时为:9
累加1000次,得到结果1000
由上面可知使用基本类型的原子操作类进行数字的自增,不仅可以保证操作操作的原子性,而且相对来说花费的时间代价比使用synchronized加锁的时间代价要小。
2.数组类型
以下以AtomicIntegerArray为例通过对一个数组内的每个元素进行自增计算,从而来介绍数组类型的原子类的运用。
package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicIntegerArray;
public class AtomicTest {
private static final AtomicIntegerArray at=new AtomicIntegerArray(new int[5]);
private static final ExecutorService es=Executors.newFixedThreadPool(20);
public static void main(String[] args) {
// TODO Auto-generated method stub
long start=System.currentTimeMillis();
for(int i=0;i<1000;i++)
{
Thread t1=new Thread() {
public void run()
{
for(int i=0;i<5;i++)
System.out.println(Thread.currentThread().getName()+"实现了对第"+(i+1)+"个元素一次自增原子操作,结果为:"+at.incrementAndGet(i));
}
};
es.execute(t1);
}
try
{
Thread.sleep(5000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println("计算过程的耗时为:"+(System.currentTimeMillis()-start-5000));
for(int i=0;i<5;i++)
System.out.println("第"+(i+1)+"个元素累加1000次,得到结果"+at.get(i));
}
}
运行程序结果如下,其中运算过程部分给出:
pool-1-thread-3实现了对第5个元素一次自增原子操作,结果为:980
pool-1-thread-20实现了对第1个元素一次自增原子操作,结果为:989
pool-1-thread-20实现了对第2个元素一次自增原子操作,结果为:1000
pool-1-thread-20实现了对第3个元素一次自增原子操作,结果为:1000
pool-1-thread-20实现了对第4个元素一次自增原子操作,结果为:1000
pool-1-thread-20实现了对第5个元素一次自增原子操作,结果为:1000
pool-1-thread-15实现了对第5个元素一次自增原子操作,结果为:998
计算过程的耗时为:9
第1个元素累加1000次,得到结果1000
第2个元素累加1000次,得到结果1000
第3个元素累加1000次,得到结果1000
第4个元素累加1000次,得到结果1000
第5个元素累加1000次,得到结果1000
从结果可以看出,数组类型的原子类的使用,可以保证每个元素的自增等操作都满足原子性。
3.属性原子修改器
以AtomicIntegerFieldUpdater类为例,该类有一个静态方法newUpdater(Class tclass,String fieldName),则这个表示为tclass类的fieldName属性创建一个属性原子修改器,如果需要修改该属性,则只需要调用原子修改器的方法,比如addAndGet(tclass obj,int delta):该方法表示将该修改器对应的属性增加delta。以下通过代码来了解属性原子修改器的作用。
package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
class Count{
public volatile int number;
}
public class AtomicTest {
private static final AtomicIntegerFieldUpdater
private static final ExecutorService es=Executors.newFixedThreadPool(20);
public static void main(String[] args) {
// TODO Auto-generated method stub
final Count count=new Count();
long start=System.currentTimeMillis();
for(int i=0;i<1000;i++)
{
Thread t1=new Thread() {
public void run()
{
System.out.println(Thread.currentThread().getName()+"实现了一次自增原子操作,结果为:"+aifu.addAndGet(count, 1));
}
};
es.execute(t1);
}
try
{
Thread.sleep(5000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println("计算过程的耗时为:"+(System.currentTimeMillis()-start-5000));
for(int i=0;i<5;i++)
System.out.println("第"+(i+1)+"个元素累加1000次,得到结果"+count.number);
}
}
运行以上程序,得到如下结果:
pool-1-thread-17实现了一次自增原子操作,结果为:993
pool-1-thread-5实现了一次自增原子操作,结果为:992
pool-1-thread-19实现了一次自增原子操作,结果为:991
pool-1-thread-3实现了一次自增原子操作,结果为:990
pool-1-thread-15实现了一次自增原子操作,结果为:989
pool-1-thread-20实现了一次自增原子操作,结果为:988
pool-1-thread-18实现了一次自增原子操作,结果为:987
pool-1-thread-6实现了一次自增原子操作,结果为:986
pool-1-thread-7实现了一次自增原子操作,结果为:985
pool-1-thread-9实现了一次自增原子操作,结果为:984
计算过程的耗时为:10
第1个元素累加1000次,得到结果1000
第2个元素累加1000次,得到结果1000
第3个元素累加1000次,得到结果1000
第4个元素累加1000次,得到结果1000
第5个元素累加1000次,得到结果1000
从上面结果可以看出,属性原子修改器的使用也能达到原子性操作的目的。
4.引用类型
以AtomicReference类为例,通过AtomicReference
package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;
class Count{
public int count;
public Count(int count)
{
this.count=count;
}
public String toString()
{
return "这个对象的位置是:"+count;
}
}
public class AtomicTest {
private static final AtomicReference
public static void main(String[] args) {
// TODO Auto-generated method stub
Count count=new Count(1001);
long start=System.currentTimeMillis();
ar.set(count);
System.out.println("你好,"+ar.get());
Count count1=new Count(1002);
ar.compareAndSet(count, count1);//内存值与count是一样的,所以值更新为count1
System.out.println("我发生了改变:"+ar.get());
Count count2=new Count(1003);
ar.compareAndSet(count, count2);//此时内存智为count1,与count不一致,所以无法更新,因此内存值依然为count1
System.out.println("我发生了改变:"+ar.get());
}
}
运行程序,结果如下:
你好,这个对象的位置是:1001
我发生了改变:这个对象的位置是:1002
我发生了改变:这个对象的位置是:1002
以上就是Java多线程原子性操作的实现,总而言之,就是依赖atomic系列类来实现的。基本类型的类主要包括AtomicInteger、AtomicLong、AtomicBoolean等;数组类型主要包括AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray;属性原子修改器类型主要包括AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater ;引用类型主要包括AtomicReference、AtomicStampedRerence、AtomicMarkableReference。对于这些类的具体讲解可以参照本站的Java多线程教程加以学习。
你适合学Java吗?4大专业测评方法
代码逻辑 吸收能力 技术学习能力 综合素质
先测评确定适合在学习