Atomic并发包
java.util.concurrent.atomic包:在多线程环境下可以对基本数据进行原子操作,无锁的进行原子操作在Atomic包里的类基本都是使用Unsafe实现的包装类。Atomic原子类在多个线程一起执行的时候,不会被其他线程干扰。
(Atomic包里的类基本都是使用Unsafe实现的,看Unsafe源码,发现Unsafe提供了三种CAS方法,compareAndSwapObject,compareAndSwapInt和compareAndSwapLong,而CAS的源码则是native底层的。再看AtomicBoolean源码,发现其是先把Boolean转换成整型,再使用compareAndSwapInt进行CAS,所以原子更新double也可以用类似的思路来实现。)
CAS指:一个线程间共享的变量,首先在主存中会保留一份,然后每个线程的工作内存也会保留一份副本。这里说的预期值,就是线程保留的副本。当该线程从主存中获取该变量的值后,主存中该变量可能已经被其他线程刷新了,但是该线程工作内存中该变量却还是原来的值,这就是所谓的预期值了。当你要用CAS刷新该值的时候,如果发现线程工作内存和主存中不一致了,就会失败,如果一致,就可以更新成功。
AtomicInteger部分源码:
public final int getAndSet(int newValue) {
for (;;) {
int current = get();
if (compareAndSet(current, newValue))
return current;
}
}
由上AtomicInteger的getAndSet源码可以发现,当CAS发现值相同,说明线程中的数据并没有被影响直接返回current值,若不一样就为false,则线程会一直阻塞。(也可以通过CAS的这个方法去检验线程是否受到干扰)
===================
Timer 定时器
通过Timer类下调用schedule进行定时调度任务:
public static void main(String[] args) {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
System.out.println("Time..Ending...");
}
}, 5000,2000);
程序会隔5s打印,以后每隔2s周期再打印。
image.png
问:即然2000代表每隔一个周期调用,那可以设计一个变周期的吗,比如开始5s到计时一次,再1s倒计时,再2s倒计时,3s...这样下去?
答:设计两个计时器,用 i 计加数来完成:
image.png
image.png
有几个点需要注意:1.i注意要全局变量,而且内部类不能有静态方法,所以提到全局的,由于main是static静态的所以也要加上static。2.匿名内部类只能使用一次,因为是匿名找不到名字的类,所以是一次性的。
由此完成加一周期的Timer定时任务。
网友评论