欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java?CAS機(jī)制詳解

 更新時(shí)間:2023年01月18日 16:12:27   作者:氵奄不死的魚(yú)  
這篇文章主要介紹了Java?CAS機(jī)制,CAS機(jī)制是一種數(shù)據(jù)更新的方式。在具體講什么是CAS機(jī)制之前,我們先來(lái)聊下在多線(xiàn)程環(huán)境下,對(duì)共享變量進(jìn)行數(shù)據(jù)更新的兩種模式:悲觀(guān)鎖模式和樂(lè)觀(guān)鎖模式

一、什么是CAS

什么是CAS機(jī)制

CAS機(jī)制是一種數(shù)據(jù)更新的方式。在具體講什么是CAS機(jī)制之前,我們先來(lái)聊下在多線(xiàn)程環(huán)境下,對(duì)共享變量進(jìn)行數(shù)據(jù)更新的兩種模式:悲觀(guān)鎖模式和樂(lè)觀(guān)鎖模式。

悲觀(guān)鎖更新的方式認(rèn)為:在更新數(shù)據(jù)的時(shí)候大概率會(huì)有其他線(xiàn)程去爭(zhēng)奪共享資源,所以悲觀(guān)鎖的做法是:第一個(gè)獲取資源的線(xiàn)程會(huì)將資源鎖定起來(lái),其他沒(méi)爭(zhēng)奪到資源的線(xiàn)程只能進(jìn)入阻塞隊(duì)列,等第一個(gè)獲取資源的線(xiàn)程釋放鎖之后,這些線(xiàn)程才能有機(jī)會(huì)重新?tīng)?zhēng)奪資源。synchronized就是java中悲觀(guān)鎖的典型實(shí)現(xiàn),synchronized使用起來(lái)非常簡(jiǎn)單方便,但是會(huì)使沒(méi)爭(zhēng)搶到資源的線(xiàn)程進(jìn)入阻塞狀態(tài)**,線(xiàn)程在阻塞狀態(tài)和Runnable狀態(tài)之間切換效率較低(比較慢)。比如你的更新操作其實(shí)是非??斓?,這種情況下你還用synchronized將其他線(xiàn)程都鎖住了,線(xiàn)程從Blocked狀態(tài)切換回Runnable華的時(shí)間可能比你的更新操作的時(shí)間還要長(zhǎng)。**

樂(lè)觀(guān)鎖更新方式認(rèn)為:在更新數(shù)據(jù)的時(shí)候其他線(xiàn)程爭(zhēng)搶這個(gè)共享變量的概率非常小,所以更新數(shù)據(jù)的時(shí)候不會(huì)對(duì)共享數(shù)據(jù)加鎖。但是在正式更新數(shù)據(jù)之前會(huì)檢查數(shù)據(jù)是否被其他線(xiàn)程改變過(guò),如果未被其他線(xiàn)程改變過(guò)就將共享變量更新成最新值,如果發(fā)現(xiàn)共享變量已經(jīng)被其他線(xiàn)程更新過(guò)了,就重試,直到成功為止。CAS機(jī)制就是樂(lè)觀(guān)鎖的典型實(shí)現(xiàn)。

CAS,是Compare and Swap的簡(jiǎn)稱(chēng),在這個(gè)機(jī)制中有三個(gè)核心的參數(shù):

  • 主內(nèi)存中存放的共享變量的值:V(一般情況下這個(gè)V是內(nèi)存的地址值,通過(guò)這個(gè)地址可以獲得內(nèi)存中的值)
  • 工作內(nèi)存中共享變量的副本值,也叫預(yù)期值:A
  • 需要將共享變量更新到的最新值:B

CAS,compare and swap的縮寫(xiě),中文翻譯成比較并交換。

CAS 操作包含三個(gè)操作數(shù) —— 內(nèi)存位置(V)、預(yù)期原值(A)和新值(B)。 如果內(nèi)存位置的值與預(yù)期原值相匹配,那么處理器會(huì)自動(dòng)將該位置值更新為新值 。否則,處理器不做任何操作。

為何CAS如此優(yōu)秀

硬件加持,現(xiàn)代大多數(shù)處理器都從硬件層面通過(guò)一些列指令實(shí)現(xiàn)CompareAndSwap(比較并交換)同步原語(yǔ),進(jìn)而使操作系統(tǒng)和JVM可以直接使用這些指令實(shí)現(xiàn)鎖和并發(fā)的數(shù)據(jù)結(jié)構(gòu)。我們可以簡(jiǎn)單認(rèn)為,CAS是將比較和交換合成是一個(gè)原子操作。

JVM對(duì)CAS的支持, 由于Java程序運(yùn)行在JVM上,所以應(yīng)對(duì)不同的硬件體系架構(gòu)的處理則需要JVM來(lái)實(shí)現(xiàn)。在不支持CAS操作的硬件上,jvm將使用自旋鎖來(lái)實(shí)現(xiàn)。

CAS為什么要和volitile配合使用

cas保證原子性。volitile保證可見(jiàn)性和有序性,二者加起來(lái),保證線(xiàn)程安全!

二、Java中的Atomic原子操作包

JUC 并發(fā)包中原子類(lèi) , 都存放在 java.util.concurrent.atomic 類(lèi)路徑下:

根據(jù)操作的目標(biāo)數(shù)據(jù)類(lèi)型,可以將 JUC 包中的原子類(lèi)分為 4 類(lèi):

基本原子類(lèi)

數(shù)組原子類(lèi)

原子引用類(lèi)型

字段更新原子類(lèi)

1. 基本原子類(lèi)

基本原子類(lèi)的功能,是通過(guò)原子方式更新 Java 基礎(chǔ)類(lèi)型變量的值?;驹宇?lèi)主要包括了以下三個(gè):

  • AtomicInteger:整型原子類(lèi)。
  • AtomicLong:長(zhǎng)整型原子類(lèi)。
  • AtomicBoolean :布爾型原子類(lèi)。

2. 數(shù)組原子類(lèi)

數(shù)組原子類(lèi)的功能,是通過(guò)原子方式更數(shù)組里的某個(gè)元素的值。數(shù)組原子類(lèi)主要包括了以下三個(gè):

  • AtomicIntegerArray:整型數(shù)組原子類(lèi)。
  • AtomicLongArray:長(zhǎng)整型數(shù)組原子類(lèi)。
  • AtomicReferenceArray :引用類(lèi)型數(shù)組原子類(lèi)。

3. 引用原子類(lèi)(可以獎(jiǎng)多個(gè)數(shù)據(jù)聚合成一個(gè)對(duì)象坐cas操作,但是不要直接修改原對(duì)象,而是每次復(fù)制處新對(duì)象,在新對(duì)象生更改后,通過(guò)cas設(shè)置回去)。

引用原子類(lèi)主要包括了以下三個(gè):

  • AtomicReference:引用類(lèi)型原子類(lèi)
  • AtomicMarkableReference :帶有更新標(biāo)記位的原子引用類(lèi)型。
  • AtomicStampedReference :帶有更新版本號(hào)的原子引用類(lèi)型。

AtomicStampedReference通過(guò)引入“版本”的概念,來(lái)解決ABA的問(wèn)題。

4. 字段更新原子類(lèi)

字段更新原子類(lèi)主要包括了以下三個(gè):

  • AtomicIntegerFieldUpdater:原子更新整型字段的更新器。
  • AtomicLongFieldUpdater:原子更新長(zhǎng)整型字段的更新器。
  • AtomicReferenceFieldUpdater:原子更新引用類(lèi)型里的字段。

三、類(lèi)AtomicInteger

1、常用的方法:

方法 介紹

public final int get() 獲取當(dāng)前的值

public final int getAndSet(int newValue) 獲取當(dāng)前的值,然后設(shè)置新的值

public final int getAndIncrement() 獲取當(dāng)前的值,然后自增

public final int getAndDecrement() 獲取當(dāng)前的值,然后自減

public final int getAndAdd(int delta) 獲取當(dāng)前的值,并加上預(yù)期的值

boolean compareAndSet(int expect, int update) 通過(guò) CAS 方式設(shè)置整數(shù)值

AtomicInteger 案例:

 private static void out(int oldValue,int newValue){
        System.out.println("舊值:"+oldValue+",新值:"+newValue);
    }
    public static void main(String[] args) {
        int value = 0;
        AtomicInteger atomicInteger= new AtomicInteger(0);
        //取值,然后設(shè)置一個(gè)新值
        value = atomicInteger.getAndSet(3);
        //舊值:0,新值:3
        out(value,atomicInteger.get());
        //取值,然后自增
        value = atomicInteger.getAndIncrement();
        //舊值:3,新值:4
        out(value,atomicInteger.get());
        //取值,然后增加 5
        value = atomicInteger.getAndAdd(5);
        //舊值:4,新值:9
        out(value,atomicInteger.get());
        //CAS 交換
        boolean flag = atomicInteger.compareAndSet(9, 100);
        //舊值:4,新值:100
        out(value,atomicInteger.get());
    }

2、AtomicInteger 源碼解析:

public class AtomicInteger extends Number implements java.io.Serializable {
    // 設(shè)置使用Unsafe.compareAndSwapInt進(jìn)行更新
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                    (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) {
            throw new Error(ex);
        }
    }
    ...省略
    private volatile int value;
    //自動(dòng)設(shè)置為給定值并返回舊值。
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }
    //以原子方式將當(dāng)前值加1并返回舊值。
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
    //以原子方式將當(dāng)前值減1并返回舊值。
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }
    //原子地將給定值添加到當(dāng)前值并返回舊值。
    public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }
    ...省略
}

通過(guò)源碼我們發(fā)現(xiàn)AtomicInteger的增減操作都調(diào)用了Unsafe 實(shí)例的方法,下面我們對(duì)Unsafe類(lèi)做介紹:

四、Unsafe類(lèi)

Unsafe 是位于 sun.misc 包下的一個(gè)類(lèi),Unsafe 提供了CAS 方法,直接通過(guò)native 方式(封裝 C++代碼)調(diào)用了底層的 CPU 指令 cmpxchg。

Unsafe類(lèi),翻譯為中文:危險(xiǎn)的,Unsafe全限定名是 sun.misc.Unsafe,從名字中我們可以看出來(lái)這個(gè)類(lèi)對(duì)普通程序員來(lái)說(shuō)是“危險(xiǎn)”的,一般應(yīng)用開(kāi)發(fā)者不會(huì)用到這個(gè)類(lèi)。

1、Unsafe 提供的 CAS 方法

主要如下: 定義在 Unsafe 類(lèi)中的三個(gè) “比較并交換”原子方法

/*
@param o 包含要修改的字段的對(duì)象
@param offset 字段在對(duì)象內(nèi)的偏移量
@param expected 期望值(舊的值)
@param update 更新值(新的值)
@return true 更新成功 | false 更新失敗
*/
public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object update);
public final native boolean compareAndSwapInt( Object o, long offset, int expected,int update);
public final native boolean compareAndSwapLong( Object o, long offset, long expected, long update);

Unsafe 提供的 CAS 方法包含四個(gè)入?yún)ⅲ?包含要修改的字段對(duì)象、字段內(nèi)存位置、預(yù)期原值及

新值。在執(zhí)行 Unsafe 的 CAS 方法的時(shí)候,這些方法首先將內(nèi)存位置的值與預(yù)期值(舊的值)比

較,如果相匹配,那么處理器會(huì)自動(dòng)將該內(nèi)存位置的值更新為新值,并返回 true ;如果不相匹配,

處理器不做任何操作,并返回 false 。

2、獲取屬性偏移量

Unsafe 提供的獲取字段(屬性)偏移量的相關(guān)操作,主要如下:

/**
* @param o 需要操作屬性的反射 
* @return 屬性的偏移量 
*/ 
public native long staticFieldOffset(Field field); 
public native long objectFieldOffset(Field field);

staticFieldOffset 方法用于獲取靜態(tài)屬性 Field 在 Class 對(duì)象中的偏移量,在 CAS 操作靜態(tài)屬性時(shí),會(huì)用到這個(gè)偏移量。

objectFieldOffset 方法用于獲取非靜態(tài) Field (非靜態(tài)屬性)在 Object 實(shí)例中的偏移量,在 CAS 操作對(duì)象的非靜態(tài)屬性時(shí),會(huì)用到這個(gè)偏移量。

3、根據(jù)屬性的偏移量獲取屬性的最新值:

/**
* @param o 字段所屬于的對(duì)象實(shí)例
* @param fieldOffset 字段的偏移量 
* @return 字段的最新值
*/
public native int getIntVolatile(Object o, long fieldOffset);

五、CAS的缺點(diǎn)

ABA問(wèn)題。因?yàn)镃AS需要在操作值的時(shí)候檢查下值有沒(méi)有發(fā)生變化,如果沒(méi)有發(fā)生變化則更新,但是如果一個(gè)值原來(lái)是A,變成了B,又變成了A,那么使用CAS進(jìn)行檢查時(shí)會(huì)發(fā)現(xiàn)它的值沒(méi)有發(fā)生變化,但是實(shí)際上卻變化了。

JDK 提供了兩個(gè)類(lèi) AtomicStampedReference、AtomicMarkableReference 來(lái)解決 ABA 問(wèn)題。

只能保證一個(gè)共享變量的原子操作。一個(gè)比較簡(jiǎn)單的規(guī)避方法為:把多個(gè)共享變量合并成一個(gè)共享變量來(lái)操作。 JDK 提供了 AtomicReference 類(lèi)來(lái)保證引用對(duì)象之間的原子性,可以把多個(gè)變量放在一個(gè) AtomicReference 實(shí)例后再進(jìn)行 CAS 操作。比如有兩個(gè)共享變量 i=1、j=2,可以將二者合并成一個(gè)對(duì)象,然后用 CAS 來(lái)操作該合并對(duì)象的 AtomicReference 引用。

循環(huán)時(shí)間長(zhǎng)開(kāi)銷(xiāo)大。高并發(fā)下N多線(xiàn)程同時(shí)去操作一個(gè)變量,會(huì)造成大量線(xiàn)程CAS失敗,然后處于自旋狀態(tài),導(dǎo)致嚴(yán)重浪費(fèi)CPU資源,降低了并發(fā)性。

解決 CAS 惡性空自旋的較為常見(jiàn)的方案為:

分散操作熱點(diǎn),使用 LongAdder 替代基礎(chǔ)原子類(lèi) AtomicLong。

使用隊(duì)列削峰,將發(fā)生 CAS 爭(zhēng)用的線(xiàn)程加入一個(gè)隊(duì)列中排隊(duì),降低 CAS 爭(zhēng)用的激烈程度。JUC 中非常重要的基礎(chǔ)類(lèi) AQS(抽象隊(duì)列同步器)就是這么做的。

六、以空間換時(shí)間LongAdder 

1、LongAdder 的原理

LongAdder 的基本思路就是分散熱點(diǎn), 如果有競(jìng)爭(zhēng)的話(huà),內(nèi)部維護(hù)了多個(gè)Cell變量,每個(gè)Cell里面有一個(gè)初始值為0的long型變量, 不同線(xiàn)程會(huì)命中到數(shù)組的不同Cell (槽 )中,各個(gè)線(xiàn)程只對(duì)自己Cell(槽) 中的那個(gè)值進(jìn)行 CAS 操作。這樣熱點(diǎn)就被分散了,沖突的概率就小很多。 在沒(méi)有競(jìng)爭(zhēng)的情況下,要累加的數(shù)通過(guò) CAS 累加到 base 上。 如果要獲得完整的 LongAdder 存儲(chǔ)的值,只要將各個(gè)槽中的變量值累加,后的值即可。

七、使用AtomicStampedReference解決ABA問(wèn)題

JDK 的提供了一個(gè)類(lèi)似 AtomicStampedReference 類(lèi)來(lái)解決 ABA 問(wèn)題。

AtomicStampReference 在 CAS 的基礎(chǔ)上增加了一個(gè) Stamp 整型 印戳(或標(biāo)記),使用這個(gè)印戳可以來(lái)覺(jué)察數(shù)據(jù)是否發(fā)生變化,給數(shù)據(jù)帶上了一種實(shí)效性的檢驗(yàn)。

AtomicStampReference 的 compareAndSet 方法首先檢查當(dāng)前的對(duì)象引用值是否等于預(yù)期引用, 并且當(dāng)前印戳( Stamp )標(biāo)志是否等于預(yù)期標(biāo)志,如果全部相等,則以原子方式將引用值和印戳 ( Stamp )標(biāo)志的值更新為給定的更新值。 1、AtomicStampReference 的構(gòu)造器:

/**  
* @param initialRef初始引用  
* @param initialStamp初始戳記  
*\ 
AtomicStampedReference(V initialRef, int initialStamp)

2、AtomicStampReference 的常用的幾個(gè)方法如下:

方法 介紹

public V getRerference() 引用的當(dāng)前值 public int getStamp() 返回當(dāng)前的"戳記"

public boolean weakCompareAndSet(V   expectedReference,
                                 V   newReference,
                                 int expectedStamp,
                                 int newStamp)
expectedReference 引用的舊值
newReference 引用的新值
expectedStamp 舊的戳記
newStamp 新的戳記  
    public static void main(String[] args) {
        boolean success = false;
        AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<Integer>(1, 0);
        int stamp = atomicStampedReference.getStamp();
        success = atomicStampedReference.compareAndSet(1, 0, stamp, stamp + 1);
        System.out.println("success:" + success + ";reference:" + "" + atomicStampedReference.getReference() + ";stamp:" + atomicStampedReference.getStamp());
        //修改印戳,更新失敗
        stamp = 0;
        success = atomicStampedReference.compareAndSet(0, 1, stamp, stamp + 1);
        System.out.println("success:" + success + ";reference:" + "" + atomicStampedReference.getReference() + ";stamp:" + atomicStampedReference.getStamp());
    }

八、AtomicIntegerFieldUpdater進(jìn)行字段更新

如果一個(gè)類(lèi)是自己編寫(xiě)的,則可以在編寫(xiě)的時(shí)候把成員變量定義為Atomic類(lèi)型。但如果是一個(gè)已經(jīng)有的類(lèi),在不能更改其源代碼的情況下,要想實(shí)現(xiàn)對(duì)其成員變量的原子操作,就需要AtomicIntegerFieldUpdater、AtomicLongFieldUpdater 和 AtomicReferenceFieldUpdater。

    public static void main(String[] args) {
        Student student = new Student();
        //創(chuàng)建AtomicIntegerFieldUpdater對(duì)象
        AtomicIntegerFieldUpdater<Student> studentAtomicIntegerFieldUpdater = AtomicIntegerFieldUpdater.newUpdater(Student.class, "age");
        //打印age并將age+1
        System.out.println(studentAtomicIntegerFieldUpdater.getAndIncrement(student));
        System.out.println(student.age);
    }
//測(cè)試類(lèi)   
public class Student {
	//因?yàn)槭怯梅瓷鋵?shí)現(xiàn)的這里必須要使用public修飾
    public volatile int  age;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

要修改的age必須是int不能是包裝類(lèi)Integer,必須被volatile修飾

if (field.getType() != int.class)
throw new IllegalArgumentException("Must be integer type");
if ( ! Modifier.isVolatile(modifiers))
throw new IllegalArgumentException( "Must be volation type");

AtomicIntegerFieldUpdater代碼實(shí)現(xiàn)

	//AtomicIntegerFieldUpdater的無(wú)參構(gòu)造被protected修飾,使用newUpdater創(chuàng)建對(duì)象
    protected AtomicIntegerFieldUpdater() {
    }
    public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
                                                              String fieldName) {
        return new AtomicIntegerFieldUpdaterImpl<U>
            (tclass, fieldName, Reflection.getCallerClass());
    }
        public final int getAndIncrement(T obj) {
        	//age+1
            return getAndAdd(obj, 1);
        }
        public final int getAndAdd(T obj, int delta) {
        	//檢查obj和聲明AtomicIntegerFieldUpdater時(shí)的class一不一樣
            accessCheck(obj);
            //Unsafe類(lèi)獲得age的值并且使用compareAndSwapInt將age+1
            return U.getAndAddInt(obj, offset, delta);
        }

AtomicLongFieldUpdater 和 AtomicReferenceFieldUpdater和AtomicIntegerFieldUpdater類(lèi)似

到此這篇關(guān)于Java CAS機(jī)制詳解的文章就介紹到這了,更多相關(guān)Java CAS內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java?AQS?線(xiàn)程安全同步隊(duì)列的實(shí)現(xiàn)

    Java?AQS?線(xiàn)程安全同步隊(duì)列的實(shí)現(xiàn)

    AQS 同步隊(duì)列是很多的 Java 線(xiàn)程安全對(duì)象的實(shí)現(xiàn),例如 ReentrantLock, Semaphore, CountDownLatch, ReentrantReadWriteLock 等等,本文就介紹了Java?AQS?線(xiàn)程安全同步隊(duì)列的實(shí)現(xiàn),感興趣的可以了解一下
    2023-08-08
  • Java詳細(xì)講解堆排序與時(shí)間復(fù)雜度的概念

    Java詳細(xì)講解堆排序與時(shí)間復(fù)雜度的概念

    本文主要介紹了java實(shí)現(xiàn)堆排序以及時(shí)間復(fù)雜度,堆排序這種排序算法是我們經(jīng)常用到的,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Java中結(jié)束循環(huán)的方法

    Java中結(jié)束循環(huán)的方法

    這篇文章主要介紹了Java中結(jié)束循環(huán)的方法,文中有段代碼在return,結(jié)束了整個(gè)main方法,即使輸出hello world的語(yǔ)句位于循環(huán)體外,也不會(huì)被執(zhí)行,對(duì)java結(jié)束循環(huán)方法感興趣的朋友跟隨小編一起看看吧
    2023-06-06
  • 使用Java如何將圖片轉(zhuǎn)成Base64編碼,并壓縮至40k

    使用Java如何將圖片轉(zhuǎn)成Base64編碼,并壓縮至40k

    這篇文章主要介紹了使用Java如何將圖片轉(zhuǎn)成Base64編碼,并壓縮至40k問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • JAVA 對(duì)接騰訊云直播的實(shí)現(xiàn)

    JAVA 對(duì)接騰訊云直播的實(shí)現(xiàn)

    這篇文章主要介紹了JAVA 對(duì)接騰訊云直播的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • java中使用map排序的實(shí)例講解

    java中使用map排序的實(shí)例講解

    在本篇文章里小編給大家整理了一篇關(guān)于java中使用map排序的實(shí)例講解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2020-12-12
  • Java 實(shí)現(xiàn)麥克風(fēng)自動(dòng)錄音

    Java 實(shí)現(xiàn)麥克風(fēng)自動(dòng)錄音

    這篇文章主要介紹了Java 實(shí)現(xiàn)麥克風(fēng)自動(dòng)錄音的示例代碼,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-12-12
  • SWT JFace 小制作 文本閱讀器

    SWT JFace 小制作 文本閱讀器

    SWT JFace 小制作 文本閱讀器
    2009-06-06
  • 淺談Java中Properties類(lèi)的詳細(xì)使用

    淺談Java中Properties類(lèi)的詳細(xì)使用

    properties類(lèi)繼承自hashtable,通常和io流結(jié)合使用。它最突出的特點(diǎn)是將key/value作為配置屬性寫(xiě)入到配置文件中以實(shí)現(xiàn)配置持久化,或從配置文件中讀取這些屬性。它的這些配置文件的規(guī)范后綴名為".properties"。表示了一個(gè)持久的屬性集
    2021-06-06
  • 詳解使用Spring AOP和自定義注解進(jìn)行參數(shù)檢查

    詳解使用Spring AOP和自定義注解進(jìn)行參數(shù)檢查

    本篇文章主要介紹了詳解使用Spring AOP和自定義注解進(jìn)行參數(shù)檢查,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04

最新評(píng)論