JDK1.5 AtomicLong****实例
类 AtomicLong
可以用原子方式更新的 long 值。有关原子变量属性的描述,请参阅 java.util.concurrent.atomic 包规范。AtomicLong 可用在应用程序中(如以原子方式增加的序列号),并且不能用于替换 Long。但是,此类确实扩展了 Number,允许那些处理基于数字类的工具和实用工具进行统一访问。
常见方法
long addAndGet(long delta):以原子方式将给定值与当前值相加。
boolean compareAndSet(long expect, long update):如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
long decrementAndGet():以原子方式将当前值减 1。
double doubleValue():以 double 形式返回指定的数值。
float floatValue():以 float 形式返回指定的数值。
long get():获取当前值。
软件包 java.util.concurrent.atomic
类的小工具包,支持在单个变量上解除锁定的线程安全编程。
类摘要
AtomicBoolean
可以用原子方式更新的 boolean 值。
AtomicInteger
可以用原子方式更新的 int 值。
AtomicIntegerArray
可以用原子方式更新其元素的 int 数组。
AtomicIntegerFieldUpdater
基于反射的实用工具,可以对指定类的指定 volatile int 字段进行原子更新。
AtomicLong
可以用原子方式更新的 long 值。
AtomicLongArray
可以用原子方式更新其元素的 long 数组。
AtomicLongFieldUpdater
基于反射的实用工具,可以对指定类的指定 volatile long 字段进行原子更新。
AtomicMarkableReference
AtomicMarkableReference 维护带有标记位的对象引用,可以原子方式对其进行更新。
AtomicReference
可以用原子方式更新的对象引用。
AtomicReferenceArray
可以用原子方式更新其元素的对象引用数组。
AtomicReferenceFieldUpdater<T,V>
基于反射的实用工具,可以对指定类的指定 volatile reference 字段进行原子更新。
AtomicStampedReference
AtomicStampedReference 维护带有整数“标志”的对象引用,可以原子方式对其进行更新。
实例1:
package com.bijian.thread;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
public class MyRunnable implements Runnable {
private static AtomicLong aLong = new AtomicLong(10000); // 原子量,每个线程都可以自由操作
private String name; // 操作人
private int x; // 操作数额
private Lock lock;
MyRunnable(String name, int x, Lock lock) {
this.name = name;
this.x = x;
this.lock = lock;
}
public void run() {
System.out.println(name + "执行了" + x + ",当前余额:" + aLong.addAndGet(x));
aLong.addAndGet(1);
}
}
package com.bijian.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(2);
Lock lock = new ReentrantLock(false);
Runnable t1 = new MyRunnable("张三", 2000, lock);
Runnable t2 = new MyRunnable("李四", 3600, lock);
Runnable t3 = new MyRunnable("王五", 2700, lock);
Runnable t4 = new MyRunnable("老张", 600, lock);
Runnable t5 = new MyRunnable("老牛", 1300, lock);
Runnable t6 = new MyRunnable("胖子", 800, lock);
// 执行各个线程
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
pool.execute(t6);
// 关闭线程池
pool.shutdown();
}
}
运行结果:
- 李四执行了3600,当前余额:13600
- 张三执行了2000,当前余额:15600
- 王五执行了2700,当前余额:18302
- 老张执行了600,当前余额:18903
- 老牛执行了1300,当前余额:20203
- 胖子执行了800,当前余额:21004
**应该是每个线程执行后都会执行aLong.addAndGet(1);****语句,但实际结果却不是这样的,原因是:虽然long addAndGet(long delta)**方法是以原子方式将给定值与当前值相加,但两条两句在一块,也只能表示它们各自的执行是原子级的,它们作为一个整体却不是原子级的。
于是,我们稍微修改一下MyRunnable类,给它加上锁,即可达到我们预想的目的,如下实例2所示。
实例2(修改MyRunnable类):
package com.bijian.thread;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
public class MyRunnable implements Runnable {
private static AtomicLong aLong = new AtomicLong(10000); // 原子量,每个线程都可以自由操作
private String name; // 操作人
private int x; // 操作数额
private Lock lock;
MyRunnable(String name, int x, Lock lock) {
this.name = name;
this.x = x;
this.lock = lock;
}
public void run() {
lock.lock();
System.out.println(name + "执行了" + x + ",当前余额:" + aLong.addAndGet(x));
aLong.addAndGet(1);
lock.unlock();
}
}
运行结果:
- 张三执行了2000,当前余额:12000
- 李四执行了3600,当前余额:15601
- 王五执行了2700,当前余额:18302
- 老张执行了600,当前余额:18903
- 胖子执行了800,当前余额:19704
- 老牛执行了1300,当前余额:21005