最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java內(nèi)存模型JMM與volatile

 更新時間:2022年07月29日 14:25:06   作者:Hz488  
這篇文章主要介紹了Java內(nèi)存模型JMM與volatile,Java內(nèi)存模型是一種抽象的概念,并不真實存在,它描述的是一組規(guī)則或規(guī)范,定義了程序中各個變量的訪問方式

1.Java內(nèi)存模型

JAVA定義了一套在多線程讀寫共享數(shù)據(jù)時時,對數(shù)據(jù)的可見性、有序性和原子性的規(guī)則和保障。屏蔽掉不同操作系統(tǒng)間的微小差異。

Java內(nèi)存模型(Java Memory Model)是一種抽象的概念,并不真實存在,它描述的是一組規(guī)則或規(guī)范(定義了程序中各個變量的訪問方式)。 JVM運行程序的實體是線程,而每個線程創(chuàng)建時 JVM 都會為其創(chuàng)建一個工作內(nèi)存(??臻g),用于存儲線程私有的數(shù)據(jù),而Java 內(nèi)存模型中規(guī)定所有變量都存儲在主內(nèi)存,主內(nèi)存是共享內(nèi)存區(qū)域,所有線程都可以訪問, 但線程對變量的操作(讀取賦值等)必須在工作內(nèi)存中進(jìn)行。所以首先要將變量從主內(nèi)存拷貝的自己的工作內(nèi)存空間,然后對變量進(jìn)行操作,操作完成后再將變量寫回主內(nèi)存,不能直接操作主內(nèi)存中的變量。工作內(nèi)存是每個線程的私有數(shù)據(jù)區(qū)域,因此不同的線程間無法訪問對方的工作內(nèi)存,線程間的通信(傳值)必須通過主內(nèi)存來完成。

基于JMM規(guī)范的線程,工作內(nèi)存,主內(nèi)存工作交互圖 :

  • 主內(nèi)存: 線程的共享數(shù)據(jù)區(qū)域,主要存儲的是Java實例對象,所有線程創(chuàng)建的實例對象都存放在主內(nèi)存中(包括局部變量、類信息、常量、靜態(tài)變量)。
  • 工作內(nèi)存: 線程私有,主要存儲當(dāng)前方法的所有本地變量信息(主內(nèi)存中的變量副本拷貝) , 每個線程只能訪問自己的工作內(nèi)存,即線程中的本地變量對其它線程是不可見的,即使訪問的是同一個共享變量。

對于一個實例對象中的成員方法: 如果方法中包含本地變量是基本數(shù)據(jù)類型,將直接存儲在工作內(nèi)存的幀棧結(jié)構(gòu)中,如果是引用類型,那么該變量的引用會存儲在功能內(nèi)存的幀棧中,而對象實例將存儲在主內(nèi)存(共享數(shù)據(jù)區(qū)域,堆)中。

需要注意的是,在主內(nèi)存中的實例對象可以被多線程共享,倘若兩個線程同時調(diào)用了同一個對象的同一個方法,那么兩條線程會將要操作的數(shù)據(jù)拷貝一份到自己的工作內(nèi)存中,執(zhí)行完成操作后才刷新到主內(nèi)存

下面是線程讀取共享變量count執(zhí)行count + 1 操作的過程:

數(shù)據(jù)同步八大原子操作:

  • (1)lock(鎖定): 作用于主內(nèi)存的變量,把一個變量標(biāo)記為一條線程獨占狀態(tài)
  • (2)unlock(解鎖): 作用于主內(nèi)存的變量,把一個處于鎖定狀態(tài)的變量釋放出來,釋放后 的變量才可以被其他線程鎖定
  • (3)read(讀取): 作用于主內(nèi)存的變量,把一個變量值從主內(nèi)存?zhèn)鬏數(shù)骄€程的工作內(nèi)存 中,以便隨后的load動作使用
  • (4)load(載入): 作用于工作內(nèi)存的變量,它把read操作從主內(nèi)存中得到的變量值放入工 作內(nèi)存的變量副本中
  • (5)use(使用): 作用于工作內(nèi)存的變量,把工作內(nèi)存中的一個變量值傳遞給執(zhí)行引擎
  • (6)assign(賦值): 作用于工作內(nèi)存的變量,它把一個從執(zhí)行引擎接收到的值賦給工作內(nèi) 存的變量
  • (7)store(存儲): 作用于工作內(nèi)存的變量,把工作內(nèi)存中的一個變量的值傳送到主內(nèi)存 中,以便隨后的write的操作
  • (8)write(寫入): 作用于工作內(nèi)存的變量,它把store操作從工作內(nèi)存中的一個變量的值 傳送到主內(nèi)存的變量中

2.并發(fā)三大特性

2.1.原子性

定義: 一個操作在CPU中不可以中途暫停再調(diào)度,要么全部執(zhí)行完成,要么全部都不執(zhí)行

問題: 兩個線程對初始值的靜態(tài)變量一個做自增,一個做自減同樣做10000次的結(jié)果很可能不是 0

解決關(guān)鍵字: synchronized、ReentrantLock 建議:

  • 用sychronized對對象加鎖的力度建議大一點(減少加解鎖次數(shù))
  • 鎖住同一個對象

2.2.可見性

定義: 當(dāng)多個線程訪問同一個變量時,一個線程修改了這個變量的值,其他線程立即看得到修改的值。(即時性)

問題: 兩個線程在不同的 CPU ,若線程1改變了變量 i 的值,還未刷新到主存,線程2又使用了 i,那么線程2看到的這個值肯定還是之前的

//線程1
boolean stop = false;
while(stop){
    ....
}
//線程2
stop = true;
//并未退出循環(huán)

解決關(guān)鍵字: synchronized、volatile

volatile 關(guān)鍵字,它可以用來修飾成員變量和靜態(tài)成員變量,避免線程從自己的工作內(nèi)存中查找變量值,必須到主存中獲取它的值,線程操作volatile變量都是直接操作主內(nèi)存,還可以禁止指令重排。 synchronized語句塊既可以保證代碼的原子性,也可以保證代碼塊內(nèi)部的可見性,但是呢synchronized屬于重量級操作,性能相對更低

注意: 對于上述循環(huán)代碼塊,加入System.out.println(); 會退出循環(huán),因為 println 被 synchronized 修飾,所有,不要隨便在代碼中使用這種打印語句,會極度影響程序性能。

2.3.有序性

定義: 虛擬機(jī)在進(jìn)行代碼編譯時,對改變順序后不會對最終結(jié)果造成影響的代碼,虛擬機(jī)不一定會按我們寫的代碼順序運行,有可能進(jìn)行重排序。實際上雖然重排后不會對變量值有影響,但會造成線程安全問題。

解決關(guān)鍵字: synchronized、ReentrantLock  volatile關(guān)鍵字,可以禁止指令重排

指令重排: JIT 編譯器在運行時的一些優(yōu)化,可以提升 CPU 的執(zhí)行效率,不讓 CPU 空閑下來。對改變順序后不會對最終結(jié)果造成影響的代碼,虛擬機(jī)不一定會按我們寫的代碼順序運行,有可能進(jìn)行重排序。比如說,我兩行代碼 X 和 Y,虛擬機(jī)認(rèn)為它們倆的執(zhí)行順序不影響程序結(jié)果,但 Y 已經(jīng)在 CacheLine 中存在了,就會優(yōu)先執(zhí)行 Y。

分析下面?zhèn)未a的運行情況(r.r1的值):

int num = 0;
boolean ready = false;
// 線程1 執(zhí)行此方法
public void action1(I_Result r) {
    if(ready) {
        r.r1 = num + num;
    } else {
        r.r1 = 1;
    }
}
// 線程2 執(zhí)行此方法
public void action2(I_Result r) {
    num = 2;
    ready = true;
}
情況1:線程1 先執(zhí)行,此時 ready = false,所有進(jìn)入else ,結(jié)果為1
情況2:線程2 先執(zhí)行 num = 2,但還沒來得及執(zhí)行 ready = true,線程1 開始執(zhí)行,還是進(jìn)入else ,結(jié)果為1
情況3:線程2 先執(zhí)行到ready = true,線程1 執(zhí)行,進(jìn)入else ,結(jié)果為4
情況4:指令重排導(dǎo)致,線程2執(zhí)行 ready = true,切換到線程1,進(jìn)入 if 分支,相加為0,再切回線程2,執(zhí)行 num = 2,結(jié)果為0

double-checked locking 單例模式: 也存在指令重排問題(不使用volatile,對象實例化是原子操作,但分為幾步,每一步又不是原子操作),因此需要在對象前加上 volatile 關(guān)鍵字防止指令重排,這也是個非常經(jīng)典的禁止指令重排的例子。

public class SingleLazy {
 ? ?private SingleLazy() {}
 ? ?private volatile static SingleLazy INSTANCE;
    // 獲取實體
 ? ?public static SingleLazy getInstance() {
 ? ? ? ?// 實例未被創(chuàng)建,開啟同步代碼塊準(zhǔn)備創(chuàng)建
 ? ? ? ?if (INSTANCE == null) {
 ? ? ? ? ? ?synchronized (SingleLazy.class) {
 ? ? ? ? ? ? ? ?// 也許其他線程在判斷完后已經(jīng)創(chuàng)建,再次判斷
 ? ? ? ? ? ? ? ?if (INSTANCE == null) {
 ? ? ? ? ? ? ? ? ? ?INSTANCE = new SingleLazy();
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  }
 ? ? ?  }
 ? ? ? ?return INSTANCE;
 ?  }
}

創(chuàng)建對象可以大致分為三步,其中第一步和第二步可能會發(fā)生指令重排導(dǎo)致安全性問題:

memory = allocate();//1.分配對象內(nèi)存空間
instance(memory);//2.初始化對象
instance = memory;//3.設(shè)置instance指向剛分配的內(nèi)存地址,此時instance e != null

注意: JDK1.5前的 volatile 關(guān)鍵字不保證指令重排問題

3.兩個規(guī)則

as-if-serial 語義保證單線程內(nèi)程序的執(zhí)行結(jié)果不被改變,happens-before關(guān)系保證正確同步的多線程程序的執(zhí)行結(jié)構(gòu)不被改變

3.1.happens-before規(guī)則

定義: 如果一個操作 happens-before 另一個操作,那么第一個操作的執(zhí)行結(jié)果將對第二個操作可見,而且第一個操作的執(zhí)行順序排在第二個操作之前

兩個操作之間存在 happens-before 關(guān)系,并不意味 java 平臺的具體實現(xiàn)必須按照 happens-before 關(guān)系指定的順序來執(zhí)行。如果重排序后的執(zhí)行結(jié)構(gòu),與按 happens-before 關(guān)系來執(zhí)行的結(jié)果一致,那么這種重排序并不非法(JMM允許這種重排序),happens-before 原則內(nèi)容如下:

程序順序原則 即在一個線程內(nèi)必須保證語義串行性,也就是說按照代碼順序執(zhí)行,(時間上)先執(zhí)行的操作happen-before(時間上后執(zhí)行的操作)

鎖規(guī)則 解鎖(unlock)操作必然發(fā)生在后續(xù)的同一個鎖的加鎖(lock)之前,也就是說,如果對于一個鎖解鎖后,再加鎖,那么加鎖的動作必須在解鎖動作之后(同一個鎖)。

volatile規(guī)則 volatile變量的寫,先發(fā)生于讀,這保證了volatile變量的可見性,簡 單的理解就是,volatile變量在每次被線程訪問時,都強(qiáng)迫從主內(nèi)存中讀該變量的 值,而當(dāng)該變量發(fā)生變化時,又會強(qiáng)迫將最新的值刷新到主內(nèi)存,任何時刻,不同的線程總是能夠看到該變量的最新值。

線程啟動規(guī)則 線程的start()方法先于它的每一個動作,即如果線程A在執(zhí)行線程B 的start方法之前修改了共享變量的值,那么當(dāng)線程B執(zhí)行start方法時,線程A對共享 變量的修改對線程B可見

傳遞性 A先于B ,B先于C 那么A必然先于C

線程終止規(guī)則 線程的所有操作先于線程的終結(jié),Thread.join()方法的作用是等待 當(dāng)前執(zhí)行的線程終止。假設(shè)在線程B終止之前,修改了共享變量,線程A從線程B的 join方法成功返回后,線程B對共享變量的修改將對線程A可見。

線程中斷規(guī)則 對線程 interrupt()方法的調(diào)用先行發(fā)生于被中斷線程的代碼檢測到 中斷事件的發(fā)生,可以通過Thread.interrupted()方法檢測線程是否中斷。

對象終結(jié)規(guī)則 對象的構(gòu)造函數(shù)執(zhí)行,結(jié)束先于finalize()方法

3.2.as-if-serial

不管怎么重排序(編譯器和處理器為了提高并行度),(單線程)程序的執(zhí)行結(jié)構(gòu)不能被改變。為了遵守as-if-serial 語義,編譯器和處理器不會存在數(shù)據(jù)依賴關(guān)系的操作做重排序,但是如果操作之前不存在數(shù)據(jù)依賴關(guān)系,這些操作就可能被編譯器和處理器重排序。

4.volatile

volatile是Java虛擬機(jī)提供的輕量級的同步機(jī)制,可以保證可見性,但無法保證原子性。  作用:

  • 保證可見性,也就是當(dāng)一個線程修改了一個被volatile修飾共享變量的值,新值總是可以被其他線程立即得知。即時可見通過緩存一致性協(xié)議保證
  • 禁止指令重排優(yōu)化。通過內(nèi)存屏障實現(xiàn)。
//示例
//并發(fā)場景下,count++操作不具備原子性,分為兩步先讀取值,再寫回,會出現(xiàn)線程安全問題
public class VolatileVisibility {
    public static volatile int count = 0;
    public static void increase(){
        count++;
    }
}

4.1.volatile 禁止重排優(yōu)化的實現(xiàn)

volatile 變量通過內(nèi)存屏障實現(xiàn)其可見性和禁止重排優(yōu)化。

內(nèi)存屏障: 又稱內(nèi)存柵欄,是一個CPU指令,它的作用有兩個,一是保證特定操作的執(zhí)行順序,二是保證某些變量的內(nèi)存可見性。編譯器和處理器都能執(zhí)行指令重排優(yōu)化。Intel 硬件提供了一系列的內(nèi)存屏障,主要有:Ifence(讀屏障)、sfence(寫屏障)、mfence(全能屏障,包括讀寫)、Lock前綴等。不同的硬件實現(xiàn)內(nèi)存屏障的方式不同,Java 內(nèi)存模型屏蔽了這種底層硬件平臺的差異,由 JVM 來為不同的平臺生成相應(yīng)的機(jī)器碼。 JVM 中提供了四類內(nèi)存屏障指令:

屏障類型指令說明
LoadLoadLoad1; LoadLoad; Load2保證load1的讀取操作在load2及后續(xù)讀取操作之前執(zhí)行
StoreStoreLoad1; LoadLoad; Load2在store2及其后的寫操作執(zhí)行前,保證store1的寫操作
StoreStoreStore1; StoreStore; Store2在stroe2及其后的寫操作執(zhí)行前,保證load1的讀操作
StoreLoadStore1; StoreLoad; Load2保證store1的寫操作已刷新到主內(nèi)存之后,load2及其作

volatile內(nèi)存語義的實現(xiàn): JMM 針對編譯器制定的 volatile 重排序規(guī)則表

操作普通讀寫volatile讀volatile寫
普通讀寫可以重排可以重排不可以重排
volatile讀不可以重排不可以重排不可以重排
volatile寫可以重排不可以重排不可以重排

比如第二行最后一個單元格的意思是:在程序中,當(dāng)?shù)谝粋€操作為普通變量的讀或?qū)憰r,如果第二個操作為volatile寫,則編譯器不能重排序這兩個操作。 

編譯器在生成字節(jié)碼時,會在指令序列中插入內(nèi)存屏障來禁止特定類型的處理器重排序:

  • 在每個volatile寫操作的前面插入一個StoreStore屏障
  • 在每個volatile寫操作的后面插入一個StoreLoad屏障
  • 在每個volatile讀操作的后面插入一個LoadLoad屏障
  • 在每個volatile讀操作的后面插入一個LoadStore屏障

class VolatileBarrierExample {
        int a;
        volatile int v1 = 1;
        volatile int v2 = 2;
        void readAndWrite() {
        int i = v1; // 第一個volatile讀、普通寫
        int j = v2; // 第二個volatile讀、普通寫
        a = i + j; // 普通寫 
        v1 = i + 1; // 第一個volatile寫
        v2 = j * 2; // 第二個 volatile寫
    }
}

4.2.MESI緩存一致性協(xié)議

鏈接: 認(rèn)識Java底層操作系統(tǒng)與并發(fā)基礎(chǔ).  多核CPU的情況下,如何保證緩存內(nèi)部數(shù)據(jù)的一致性?JAVA引入了MESI緩存一致性協(xié)議。 

Java代碼的執(zhí)行流程:

volatile 修飾的變量(鎖也是)翻譯的匯編指令前會加 Lock 前綴,OS調(diào)度時會 觸發(fā)硬件緩存鎖定機(jī)制(總線鎖 或 緩存一致性協(xié)議) ,CPU 通過總線橋訪問內(nèi)存條,多個 CPU 訪問同一內(nèi)存,首先需要拿到總線權(quán)。早期,計算機(jī)不發(fā)達(dá),性能低,總線鎖采用直接占有,其他 CPU 無法繼續(xù)通過總線橋訪問。無法發(fā)揮 CPU 的多核能力?,F(xiàn)代 CPU 采用采用緩存一致性協(xié)議進(jìn)行保證(跨緩存行CacheLine(緩存存儲數(shù)據(jù)的數(shù)據(jù)單元) 時會升級為總線鎖)。

MESI 是指4種狀態(tài)的首字母。每個 Cache line 有4個狀態(tài),可用2個bit表示:

狀態(tài)描述監(jiān)聽任務(wù)
M 修改(Modified)該CacheLine有效,數(shù)據(jù)被修改了,和內(nèi)存中的數(shù)據(jù)不一致,數(shù)據(jù)只存在于本Cache中緩存行必須時刻監(jiān)聽所有試圖讀該緩存行相對就主存的操作,這種操作必須在緩存將該緩存行寫回主存并將狀態(tài)變成S(共享)狀態(tài)之前被延遲執(zhí)行
E 獨享、互斥(Exclusive)該CacheLine有效,數(shù)據(jù)和內(nèi)存中的數(shù)據(jù)一致,數(shù)據(jù)只存在于本Cache中緩存行也必須監(jiān)聽其它緩存讀主存中該緩存行的操作,一旦有這種操作,該緩存行需要變成S(共享)狀態(tài)
S 共享 (Shared)該CacheLine有效,數(shù)據(jù)和內(nèi)存中的數(shù)據(jù)一致,數(shù)據(jù)存在于很多Cache中緩存行也必須監(jiān)聽其它緩存使該緩存行無效或者獨享該緩存行的請求,并將該緩存行變成無效(Invalid)
I 無效 (Invalid)該CacheLine無效

MESI 協(xié)議狀態(tài)切換過程分析:

舉例:

注意:一個 CacheLine 裝不下變量,會升級為總線鎖。

MESI優(yōu)化和他們引入的問題:  緩存的一致性消息傳遞是要時間的,這就使其切換時會產(chǎn)生延遲。當(dāng)一個緩存被切換狀態(tài)時其他緩存收到消息完成各自的切換并且發(fā)出回應(yīng)消息這么一長串的時間中CPU都會等待所有緩存響應(yīng)完成。可能出現(xiàn)的阻塞都會導(dǎo)致各種各樣的性能問題穩(wěn)定性問題。

 為了避免這種CPU運算能力的浪費,Store Bufferes 被引入使用。處理器把它想要寫入到主存的值寫到緩存,然后繼續(xù)去處理其他事情。當(dāng)所有失效確認(rèn)(Invalidate Acknowledge)都接收到時,數(shù)據(jù)才會最 終被提交。

但它也會帶來一定的風(fēng)險:

  • 處理器會嘗試從存儲緩存(Store buffer)中讀取值,但它還沒有進(jìn)行提交。這個的解決方案稱為Store Forwarding,它使得加載的時候,如果存儲緩存中存在,則進(jìn)行返回
  • 保存什么時候會完成,這個并沒有任何保證,可能會發(fā)生重排序(非指令重排)。CPU會讀到跟程序中寫入的順序不一樣的結(jié)果。

到此這篇關(guān)于Java內(nèi)存模型JMM與volatile的文章就介紹到這了,更多相關(guān)Java內(nèi)存模型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java為什么使用BlockingQueue解決競態(tài)條件問題面試精講

    java為什么使用BlockingQueue解決競態(tài)條件問題面試精講

    這篇文章主要為大家介紹了java為什么使用BlockingQueue解決競態(tài)條件問題面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • Java注解簡介和使用詳細(xì)講解

    Java注解簡介和使用詳細(xì)講解

    Java 語言中的類、構(gòu)造器、方法、成員變量、參數(shù)等都可以被注解進(jìn)行標(biāo)注,這篇文章主要介紹了Java注解的介紹和使用詳細(xì)講解,需要的朋友可以參考下
    2023-02-02
  • flowable表梳理步驟詳解

    flowable表梳理步驟詳解

    這篇文章主要介紹了flowable表梳理步驟詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • Servlet開發(fā)JavaWeb工程示例詳解

    Servlet開發(fā)JavaWeb工程示例詳解

    這篇文章主要介紹了Servlet開發(fā)JavaWeb工程示例詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • SpringBoot自定義對象參數(shù)超詳細(xì)介紹作用

    SpringBoot自定義對象參數(shù)超詳細(xì)介紹作用

    SpringBoot通過自定義對象參數(shù),可以實現(xiàn)自動類型轉(zhuǎn)換與格式化,并可以級聯(lián)封裝,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-09-09
  • Spring mvc整合tiles框架的簡單入門教程(maven)

    Spring mvc整合tiles框架的簡單入門教程(maven)

    這篇文章主要給大家介紹了關(guān)于Spring mvc整合tiles框架的簡單入門教程(maven),文中通過示例代碼介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考借鑒,下面來一起看看詳細(xì)的介紹吧。
    2017-12-12
  • Java應(yīng)用多機(jī)器部署解決大量定時任務(wù)問題

    Java應(yīng)用多機(jī)器部署解決大量定時任務(wù)問題

    這篇文章主要介紹了Java應(yīng)用多機(jī)器部署解決大量定時任務(wù)問題,兩臺服務(wù)器同時部署了同一套代碼, 代碼中寫有spring自帶的定時任務(wù),但是每次執(zhí)行定時任務(wù)時只需要一臺機(jī)器去執(zhí)行,需要的朋友可以參考下
    2019-07-07
  • java swing GUI窗口美化方式

    java swing GUI窗口美化方式

    這篇文章主要介紹了java swing GUI窗口美化方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 深入理解java內(nèi)置鎖(synchronized)和顯式鎖(ReentrantLock)

    深入理解java內(nèi)置鎖(synchronized)和顯式鎖(ReentrantLock)

    這篇文章主要介紹了Java多線程之內(nèi)置鎖(synchronized)和顯式鎖(ReentrantLock)的深入理解新的和用法,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • 使用quartz時,傳入?yún)?shù)到j(luò)ob中的使用記錄

    使用quartz時,傳入?yún)?shù)到j(luò)ob中的使用記錄

    這篇文章主要介紹了使用quartz時,傳入?yún)?shù)到j(luò)ob中的使用記錄,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12

最新評論

五寨县| 贵德县| 定兴县| 名山县| 东莞市| 昆明市| 徐州市| 辽阳县| 二手房| 定边县| 黎城县| 越西县| 宁化县| 黔东| 鄂州市| 延川县| 鄂尔多斯市| 宁阳县| 益阳市| 策勒县| 贵阳市| 鄂尔多斯市| 五大连池市| 墨脱县| 辛集市| 拜泉县| 开平市| 白朗县| 略阳县| 汝阳县| 湟源县| 元谋县| 思茅市| 新源县| 宜都市| 陇南市| 定日县| 沙洋县| 南安市| 朝阳区| 友谊县|