路边刻章店能刻公章么
2025-02-13 11:22:11
主要的
30分钟
从零开始
JavaJDK v11IntelliJIDEA v2018.3本教学为系列教学,内容连贯。本章使用的内容在之前的教学中已经详细解释过了。本章内容对零基础或基础差的同学比较友好,对有基础的同学可能比较简单。希望大家可以根据自己的实际情况选择继续阅读或者等待下一篇文章。谢谢大家的理解!
《全栈2019》第二章Java原子操作:i++是原子操作吗?什么是原子性在什么是原子性一章中介绍。
什么是比较和交换中的CAS技术在“全栈2019”Java原子操作第三章:比较和交换中CAS技术的详细说明一章中有介绍。
在“全栈2019”Java原子操作第四章:AtomicBoolean的介绍和使用中,介绍了什么是原子操作类AtomicBoolean。
在“全栈2019”Java原子操作章节第5章:AtomicInteger的介绍和使用中,介绍了什么是原子操作类AtomicInteger。
在“全栈2019”章节《Java原子操作第六章:AtomicInteger灵活操作模式》中介绍了使用原子操作类AtomicInteger实现更灵活操作模式的方法。
现在介绍原子操作类AtomicLong。
顾名思义,原子操作类是实现原子操作的类。
原子操作的概念和必要知识在全栈2019 Java原子操作第一章:内存可见性volatile关键字分析和全栈2019 Java原子操作第二章:i++是原子操作吗?什么是原子性以及《全栈2019》第三章Java原子操作:compare和swap中CAS技术的详细解释已经详细介绍过了,在此不再赘述。不清楚的朋友,请前往相关章节。
AtomicLong是一个以原子方式对长值进行操作的类。
让我们简单看一下AtomicLong类的样子:
这里需要注意的是,AtomicLong像AtomicInteger类一样继承了Number类,这意味着它不能替换Long类,而只能扩展Number类。
原子克隆类很简单,它有两种构造方法:
如下:原子长()原子长(长初始值)
这两种构造方法是常用的。
第二个构造函数AtomicLong(long initial value)可以指定初始值。
让我们使用原子克隆。
例如,当我们的一些应用程序需要生成序列号或唯一id时,可以使用AtomicLong。
如果你有更多关于原子克隆的应用场景,欢迎在评论区留言。谢谢你。
现在,让我们看看没有原子克隆会是什么样子。
序列号生成器就是一个例子。
首先,我们创建一个序列号生成器类:
然后,私有化其构造方法,以便不创建对象,而是使用其静态方法:
接下来,定义一个long类型的变量来记录当前生成的序列号:
然后,定义一种获取当前序列号的方法:
然后,定义一种生成序列号的方法:
编写了序列号生成器类。
接下来,让我们试试序列号生成器。
在主类中创建一个生成序列号任务:
然后,调用run方法中生成生成器类对象序列号的方法并输出结果:
Run()方法已完成。
然后,我们创建100个线程来生成序列号:
最后,在所有100个线程都执行了生成序列号的任务后,我们将再次生成序列号:
如果当前生成的序列号为100,则意味着每个线程都有自己唯一的序列号,该序列号是不同的;
如果当前生成的序列号不是100,则意味着存在具有相同序列号的线程,并且序列号生成器类有问题。
但在此之前,我们需要休眠1秒钟,以便生成:
示例已完成。
运行程序并执行结果:
从运行结果来看,符合预期。最终生成的序列号确实是100,生成序列号类似乎没有问题。
生成序列号真的没有问题吗?
让我们修改示例并重试。
在生成序列号的任务中,在执行生成序列号的方法之前,让用户休眠100毫秒:
该示例已重写。
运行程序并执行结果:
从运行结果来看,符合预期。当前序列号不是100,这表明生成序列号的类有问题。
怎么解决?
这时,我们的AtomicLong类就派上用场了。
我们只需要用原子克隆替换长类型:
因为AtomicLong取代了Long,所以获取序列号的方法和生成序列号的方法都必须改变。
首先,获取当前序列号的方法:
然后是生成序列号方法:
对于学习过前几章的朋友来说,get()方法和getAndIncrement()方法并不陌生,get()方法用于获取sequenceNumber的当前值;getAndIncrement()方法用于递增sequenceNumber对象的值,这相当于i++。
该示例已重写。
运行程序并执行结果:
从运行结果来看,符合预期。当前序列号为100,生成序列号类之前的问题已经解决。
至此,序列号生成器的问题已经告一段落。
让我们谈谈AtomicLong类中的一些常用方法和源代码。
对于学习过“全栈2019”Java原子操作章节第5章:AtomicInteger的介绍和使用的人来说,很容易掌握以下内容,因为只有int类型更改为long类型。
我们来看看AtomicLong类的这两个方法:get()set(long new value)。
让我们依次来看看这两种方法。
原子克隆类中get()方法的源代码:
get()方法用于获取AtomicLong对象的当前值;
AtomicLong类中set(long new value)方法的源代码:
set(long new value)方法用于设置原子克隆对象的当前值。参数newValue是我们可以指定的新值。
接下来,让我们尝试get()方法和set(long new value)方法。
新示例,不是上一节中的示例。
首先,创建原子克隆对象并指定初始值:
然后,调用value的get()方法来获取当前值:
然后,调用Value的set(long new value)方法指定一个新值:
最后,调用value的get()方法再次获取当前值,以查看新值是否设置成功:
示例已完成。
运行程序并执行结果:
从运行结果来看,符合预期。该值从0变为1。
AtomicLong类中有两个增量方法:getandincrement()incrementandget()。
其中,getAndIncrement()方法相当于i++,而incrementAndGet()方法相当于++i。
让我们依次来看看这两种方法。
原子克隆类中getAndIncrement()方法的源代码:
getAndIncrement()方法返回增量之前的值。
原子克隆类中incrementAndGet()方法的源代码:
incrementAndGet()方法返回增加的值。
接下来,让我们尝试getAndIncrement()方法和incrementAndGet()方法。
新示例,不是上一节中的示例。
首先,我们创建一个AtomicLong对象并指定初始值:
然后,调用getAndIncrement()方法:
最后,调用incrementAndGet()方法:
示例已完成。
运行程序并执行结果:
从运行结果来看,符合预期。
当首次调用getAndIncrement()方法时,该值为0。根据getAndIncrement()方法的原理,第一个输出结果是正确的。
getAndIncrement()方法递增后,值为1;
接下来,调用incrementAndGet()方法时,值为1,根据incrementAndGet()方法先递增后返回当前值的原则,第二次输出结果是正确的;
递增incrementAndGet()方法的结果是1递增,然后变成2。
说完了AtomicLong类中的递增方法,我们再来说说AtomicLong类中的递减方法。
AtomicLong类中有两个递减方法:getandDecrement()decrement get()
其中,getAndDecrement()方法相当于I-,decrementAndGet()方法相当于-i。
让我们依次来看看这两种方法。
AtomicLong类中getAndDecrement()方法的源代码:
getAndDecrement()方法用于返回减量前的值。
AtomicLong类中decrementAndGet()方法的源代码:
decrement get()方法的功能是返回递减的值。
接下来,让我们尝试getAndDecrement()方法和decrementAndGet()方法。
新示例,不是上一节中的示例。
首先,我们创建一个AtomicLong对象并指定初始值:
然后,调用getAndDecrement()方法:
最后,调用decrementAndGet()方法:
示例已完成。
运行程序并执行结果:
从运行结果来看,符合预期。
首先调用getAndDecrement()方法时,该值为0。根据getAndDecrement()方法的原理,第一个输出结果是正确的。
getAndDecrement()方法递减后,value的值为-1;
接下来调用decrementAndGet()方法时,值为-1,按照decrementAndGet()方法先递减再返回当前值的原理,第二次输出结果是正确的;
方法首先递减结果:-1递减,结果为-2。
前两节演示了自增自减。如果你想加任何一个数,比如+5,或者你想减任何一个数,比如-5,都不能用前面的方法,所以AtomicLong类也给我们提供了相应的方法。
在AtomicLong类中添加任意值有两种方法:getandadd(long delta)addandget(long delta)。
如果是加法,直接写个正数就行了;如果要做减法,直接写个负数就行了。
让我们依次来看看这两种方法。
AtomicLong类中getAndAdd(long delta)方法的源代码:
getAndAdd(long delta)方法在添加任何值之前返回该值。
AtomicLong类中addAndGet(long delta)方法的源代码:
addAndGet(long delta)方法用于在添加任何值后返回值。
接下来,让我们尝试getAndAdd(长增量)方法和addAndGet(长增量)方法。
新示例,不是上一节中的示例。
首先,我们创建一个AtomicLong对象并指定初始值:
然后,调用getAndAdd(长增量)方法:
最后,调用addAndGet(long delta)方法:
示例已完成。
运行程序并执行结果:
从运行结果来看,符合预期。
当首先调用getAndAdd(long delta)方法时,该值为0。根据getAndAdd(long delta)方法的原理,第一个输出结果是正确的。
在getAndAdd(long delta)方法添加任何值后,value的值为3;
接下来,当调用addAndGet(long delta)方法时,该值为3。根据addAndGet(long delta)方法先将任意值相加然后返回当前值的原理,第二个输出结果也是正确的。
AddAndGet(long delta)方法先将任意值相加,结果为:3加-1,结果为2。
前面几节演示了指定数字的加法或减法。如果我想自定义更新值的值怎么办?
AtomicLong类为我们提供了两种更新值的方法:getandupdate(longgunarypropertor更新函数)updateandget(longgunarypropertor更新函数)。
怎么更新?
您只需要传入LongUnaryOperator接口的实现。
让我们首先来看看LongUnaryOperator接口:
在LongUnaryOperator接口中,我们只需要实现applyAsLong(长操作数)方法:
当我们调用getandupdate(longgunaryoperator更新函数)方法或updateandget(longgunaryoperator更新函数)方法时,将传递applyAsLong(长操作数)方法中的值:
让我们依次来看看这两种方法。
AtomicLong类中getandupdate(longgunarypropertor更新函数)方法的源代码:
getandupdate(longgunaryoperator更新函数)方法用于返回更新前的值。
AtomicLong类中updateandget(longgunarypropertor更新函数)方法的源代码:
updateandget(longgunaryoperator更新函数)方法用于返回更新后的值。
接下来,让我们尝试getandupdate(longgunarypropertor更新函数)方法和updateandget(longgunarypropertor更新函数)方法。
新示例,不是上一节中的示例。
首先,我们创建一个AtomicLong对象并指定初始值:
然后,调用getandupdate(longgunaryoperator更新函数)方法:
最后,调用updateandget(longgunaryoperator更新函数)方法:
示例已完成。
运行程序并执行结果:
从运行结果来看,符合预期。
第一次调用getandupdate(longgunaryoperator更新函数)方法时,值为0。根据getandupdate(longgunaryoperator更新函数)方法的原理,第一个输出结果是正确的。
getandupdate(longgunarypropertor更新函数)方法更新为指定值后,value的值为1,即0+1 = 1;
接下来,当调用updateandget(LonggunaryOperator更新函数)方法时,值为1,根据updateandget(LonggunaryOperator更新函数)方法先更新到指定值再返回到当前值的原理,第二次输出结果是正确的;
将updateandget(longgunaryoperator更新函数)方法更新为指定值的结果为:1 * 2 = 2。
如果我们想使用AtomicLong对象以更高级和灵活的方式进行更新,我们最好使用getandaccumulate(long x,longbinaryoperator累加器函数)方法和accumulator and get(long x,longbinaryoperator累加器函数)方法。
让我们依次来看看这两种方法。
AtomicLong类中getandaccumulate(long x,longbinary运算符累加器函数)方法的源代码:
getandaccumulate(long x,longbinary运算符累加器函数)方法用于在用自定义操作更新之前返回值。
accumulatorandget(long x,longbinaryoperator累加器函数)方法在AtomicLong类中的源代码:
累加器和get(long x,longbinary运算符累加器函数)方法的作用是使用自定义操作方法返回更新后的值。
getandaccumulate(long x,longbinaryoperator累加器函数)方法和accumulator get(long x,longbinaryoperator累加器函数)方法都需要一个LongBinaryOperator类型的参数。
LongBinaryOperator是Long类型的二进制操作接口,其中只有一个applyAsLong(Long left,long right)方法:
applyAsLong(long left,long right)方法中有两个参数:left和right。
Left表示左边的操作数;
Right代表右边的操作数;
你什么意思?
比如x.applyAsLong(2,3),那么左= 2,右= 3。在AtomicLong类中,left =原始值,rigth =调用getandaccumulate (long x,longbinaryoperator累加器函数)方法和accumulator andget (long x,longbinaryoperator累加器函数)方法中的参数long x。
接下来,让我们尝试getandaccumulate (long x)方法和accumulate and get(long x)方法。
新示例,不是上一节中的示例。
首先,创建一个AtomicLong对象,并指定一个初始值,即2:
然后,调用getandaccumulate (long x,longbinary运算符累加器函数)方法。在applyAsLong(long left,long right)方法中,我们需要做乘法,即左*右:
然后,调用累加器和get (long x,longbinary运算符累加器函数)方法。如上,在applyAsLong(long left,long right)方法中,我们还需要做乘法,即左*右:
示例已完成。
运行程序并执行结果:
从运行结果来看,符合预期。
第一次运算返回当前值,即未经运算的原始值,即2。
第一次做乘法,左= 2,右= 3,结果= 6;
第二个操作返回计算值,其中left = 6,right = 2;;
第二次做乘法时,左*右= 6 * 2 = 12。
整个运算结果完全正确。
那么,使用getandaccumulate(long x)方法和accumulator function(long x)方法来完成更灵活的运算就不言而喻了。
我们之前已经在“全栈2019”Java原子操作第三章:比较和交换CAS技术的详细解释一章中了解了什么是CAS算法。
这也反映在AtomicLong类中:
compareandset(long expected value,long newValue)方法的作用是:如果value==expectedValue,则为value分配新值,否则不执行任何操作。
让我们尝试一下compareandset(长预期值,长新值)方法。
新示例,不是上一节中的示例。
首先,我们创建一个原子克隆对象并指定一个初始值,该值为0:
然后,在调用compareandset(长预期值,长新值)方法之前获取一次value的值:
然后,调用compare andset(long expected value,long new value)方法并输出该方法返回的结果:
最后,让我们再次获取value的值,看看它是否发生了变化:
该示例已重写。
运行程序并执行结果:
从运行结果来看,符合预期。
当然,您也可以将期望值更改为原始值以外的数字,这样赋值将不会成功。
最后,希望你把这个例子再写一遍,然后自己写,这样你以后就可以轻松应对类似的面试问题了。
祝大家编码愉快!
本章程序GitHub地址:
https://github . com/gor haf/Java 2019/tree/master/thread/atomic/原子地操作长值是一个类。get()方法用于获取AtomicLong对象的当前值;set(long new value)方法用于设置原子克隆对象的当前值。参数newValue是我们可以指定的新值。getAndIncrement()方法返回增量之前的值。incrementAndGet()方法返回增加的值。getAndDecrement()方法用于返回减量前的值。decrement get()方法的功能是返回递减的值。getAndAdd(long delta)方法在添加任何值之前返回该值。addAndGet(long delta)方法用于在添加任何值后返回值。getandupdate(longgunaryoperator更新函数)方法用于返回更新前的值。updateandgetthefunction(longgunaryoperator更新函数) 方法将返回更新后的值。getandaccumulate(long x,longbinary运算符累加器函数)方法用于在用自定义操作更新之前返回值。累加器和get(long x,longbinary运算符累加器函数)方法的作用是使用自定义操作方法返回更新后的值。compareandset(long expected value,long newValue)方法的作用是:如果value==expectedValue,则为value分配新值,否则不执行任何操作。
至此,Java对AtomicLong相关内容的讲解告一段落,更多内容请继续关注。
如果你有任何问题或者想了解更多前沿技术,请在下面留言或者评论,我会为你解答。
《全栈2019》Java原子操作第六章:AtomicInteger灵活操作模式
《全栈2019》Java原子操作第八章:AtomicReference的介绍和使用
加入同步学习群,一起交流,共同进步。方法一:关注头条号Gorhaf,私信“Java学习群”。方法二:微信官方账号关注Gorhaf,回复“Java学习群”。
关注我们,加入“全栈工程师学习计划”。
原创不易,未经允许不得转载!