主頁 > 軟體設計 > 清心閣--多執行緒系列之執行緒狀態和主要轉換方法(四)

清心閣--多執行緒系列之執行緒狀態和主要轉換方法(四)

2020-12-27 10:10:23 軟體設計

今天是圣誕節,在這里祝各位同學圣誕快樂Merry Christmas!
🎄,但是學習這件事情還是得繼續哦,本章小宋講一下Java執行緒的狀態和主要的轉換方法,

目錄

  • 作業系統中的執行緒狀態轉換
  • Java執行緒的6個狀態
    • NEW狀態
      • 這里引申兩個start()的問題:
    • RUNNABLE狀態
      • JVM 為何不區分ready和running?
    • BLOCKED狀態
    • WAITING狀態
    • TIMED_WAITING狀態
    • TERMINATED狀態
  • 執行緒狀態轉換
    • BLOCKED與RUNNABLE狀態的轉換
    • WAITING狀態與RUNNABLE狀態的轉換\
      • Object.wait()方法
      • Thread.join()
    • TIMED_WAITING與RUNNABLE狀態轉換
      • Thread.sleep(long)
      • Object.wait(long)
      • Thread.join(long)
    • 執行緒中斷

作業系統中的執行緒狀態轉換

首先我們來看看作業系統中的執行緒狀態轉換,

現在的作業系統中,執行緒是被視為輕量級的行程,所以作業系統執行緒的狀態其實和作業系統行程的狀態是一致的,

如圖:
在這里插入圖片描述
作業系統執行緒主要有以下三個狀態:

  • 就緒狀態(ready): 執行緒正在等待使用CPU,經調度程式呼叫之后可進入running狀態,
  • 執行狀態(running):執行緒正在使用CPU,
  • 等待狀態(waiting): 執行緒經過等待事件的呼叫或者正在等待其他資源(如I/O),

Java執行緒的6個狀態

在這里插入圖片描述

// Thread.State 原始碼
public enum State {
    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;
}

NEW狀態

處于NEW狀態的執行緒此時尚未啟動,這里的尚未啟動指的是還沒呼叫Thread實體的start()方法,

private void testStateNew() {
    Thread thread = new Thread(() -> {});
    System.out.println(thread.getState()); // 輸出 NEW 
}

從上面可以看出,只是創建了執行緒而并沒有呼叫start()方法,此時執行緒處于NEW狀態,

這里引申兩個start()的問題:

  1. 反復呼叫同一個執行緒的start()方法是否可行?
  2. 假如一個執行緒執行完畢(此時處于Terminated狀態),再次呼叫這個執行緒的start()方法是否可行?

先來看一下start()的原始碼:
在這里插入圖片描述
通過上面的start()原始碼我們可以發現有一個threadStatus的變數,start()中對它進行了判斷,如果threadStatus不等于0,呼叫start()是會直接拋出IllegalThreadStateException例外的,

接著往下看,有一個native的start0()方法,在這里插入圖片描述
這個方法里并沒有對threadStatus進行處理,到這里好像就拿這個threadStatus沒辦法了,我們debug看一下:

@Test
public void testStartMethod() {
    Thread thread = new Thread(() -> {});
    thread.start(); // 第一次呼叫
    thread.start(); // 第二次呼叫
}

我是在start()方法內部的最開始打的斷點,敘述下我這里打斷點看到的結果:

  • 第一次呼叫時threadStatus的值是0,
  • 第二次呼叫時threadStatus的值不為0,

查看當前執行緒狀態的原始碼:
在這里插入圖片描述
在這里插入圖片描述
通過對上面原始碼的觀察可以得到剛剛提出的兩個問題的結果:
兩個問題的答案都是不可行,在呼叫一次start()之后,threadStatus的值會改變(threadStatus !=0),此時再次呼叫start()方法會拋出IllegalThreadStateException例外,

比如,threadStatus為2代表當前執行緒狀態為TERMINATED,

RUNNABLE狀態

表示當前執行緒正在運行中,處于RUNNABLE狀態的執行緒在Java虛擬機中運行,也有可能在就緒狀態等待CPU分配資源,
Java中執行緒的RUNNABLE狀態(看下Thread原始碼里對RUNNABLE狀態的定義):
在這里插入圖片描述
Java執行緒的RUNNABLE狀態其實是包括了傳統作業系統執行緒的ready和running兩個狀態的,

這個時候可能會有人問了,為何 JVM 中沒有去區分這兩種狀態呢?

JVM 為何不區分ready和running?

現在的時分(time-sharing)多任務(multi-task)作業系統架構通常都是用所謂的時間分片(time quantum or time slice)方式進行搶占式(preemptive)輪轉調度(round-robin式),
更復雜一點可能會加入優先級(priority)的機制,

這個時間分片通常是很小的,一個執行緒一次最多只能在 cpu 上運行比如10-20ms 的時間(此時處于 running 狀態),也即大概只有0.01秒這一量級,時間片用后就要被切換下來放入調度佇列的末尾等待再次調度,(也即回到 ready 狀態)

如果期間進行了 I/O 的操作還會導致提前釋放時間分片,并進入等待佇列,
又或者是時間分片沒有用完就被搶占,這時也是回到 ready 狀態,

這一切換的程序稱為執行緒的背景關系切換(context switch),當然 cpu 不是簡單地把執行緒踢開就完了,還需要把被相應的執行狀態保存到記憶體(程式計數器)中以便后續的恢復執行,

顯然,10-20ms 對人而言是很快的,

如果不計切換開銷(每次在1ms 以內),相當于1秒內有50-100次切換,事實上時間片經常沒用完,執行緒就因為各種原因被中斷,實際發生的切換次數還會更多,

也這正是單核 CPU 上實作所謂的并發(concurrent)的基本原理,但其實是快速切換所帶來的假象,這有點類似一個手腳非常快的雜耍演員可以讓好多個球同時在空中運轉那般,

時間分片也是可配置的,如果不追求在多個執行緒間很快的回應,也可以把這個時間配置得大一點,以減少切換帶來的開銷,

如果是多核CPU,才有可能實作真正意義上的并發,這種情況通常也叫并行(parallel),

通常,Java的執行緒狀態是服務于監控的,如果執行緒切換得如此之快,那么區分 ready 與 running 就沒什么太大意義了,

當你看到監控上顯示是 running 時,對應的執行緒可能早就被切換下去了,甚至又再次地切換了上來,也許你只能看到 ready 與 running 兩個狀態在快速地閃爍,
當然,對于精確的性能評估而言,獲得準確的 running 時間是有必要的,

現今主流的 JVM 實作都把 Java 執行緒一一映射到作業系統底層的執行緒上,把調度委托給了作業系統,我們在虛擬機層面看到的狀態實質是對底層狀態的映射及包裝,JVM 本身沒有做什么實質的調度,把底層的 ready 及 running 狀態映射上來也沒多大意義,因此,統一成為runnable 狀態是不錯的選擇,

BLOCKED狀態

阻塞狀態,處于BLOCKED狀態的執行緒正等待鎖的釋放以進入同步區,

舉個生活中的例子:
假如今天你下班后準備去食堂吃飯,你來到食堂僅有的一個視窗,發現前面已經有個人在視窗前了,此時你必須得等前面的人從視窗離開才行,
假設你是執行緒t2,你前面的那個人是執行緒t1,此時t1占有了鎖(食堂唯一的視窗),t2正在等待鎖的釋放,所以此時t2就處于BLOCKED狀態,

WAITING狀態

等待狀態,處于等待狀態的執行緒變成RUNNABLE狀態需要其他執行緒喚醒,

呼叫如下3個方法會使執行緒進入等待狀態:

  1. Object.wait():使當前執行緒處于等待狀態直到另一個執行緒喚醒它;
  2. Thread.join():等待執行緒執行完畢,底層呼叫的是Object實體的wait方法;
  3. LockSupport.park():除非獲得呼叫許可,否則禁用當前執行緒進行執行緒調度,

我們延續上面的例子繼續解釋一下WAITING狀態:

你等了好幾分鐘現在終于輪到你了,突然你們有一個“不懂事”的經理突然來了,你看到他你就有一種不祥的預感,果然,他是來找你的,
他把你拉到一旁叫你待會兒再吃飯,說他下午要去作報告,趕緊來找你了解一下專案的情況,你心里雖然有一萬個不愿意但是你還是從食堂視窗走開了,
此時,假設你還是執行緒t2,你的經理是執行緒t1,雖然你此時都占有鎖(視窗)了,“不速之客”來了你還是得釋放掉鎖,此時你t2的狀態就是WAITING,然后經理t1獲得鎖,進入RUNNABLE狀態,
要是經理t1不主動喚醒你t2(notify、notifyAll..),可以說你t2只能一直等待了,

TIMED_WAITING狀態

超時等待狀態,執行緒等待一個具體的時間,時間到后會被自動喚醒,

呼叫如下方法會使執行緒進入超時等待狀態:

  • Thread.sleep(long millis):使當前執行緒睡眠指定時間;
  • Object.wait(long timeout):執行緒休眠指定時間,等待期間可以通過notify()/notifyAll()喚醒;
  • Thread.join(long millis):等待當前執行緒最多執行millis毫秒,如果millis為0,則會一直執行;
  • LockSupport.parkNanos(long nanos): 除非獲得呼叫許可,否則禁用當前執行緒進行執行緒調度指定時間;
  • LockSupport.parkUntil(long deadline):同上,也是禁止執行緒進行調度指定時間;

我們繼續之前的例子來解釋一下TIMED_WAITING狀態:

到了第二天中午,又到了飯點,你還是到了視窗前,
突然間想起你的同事叫你等他一起,他說讓你等他十分鐘他改個bug,
好吧,你說那你就等等吧,你就離開了視窗,很快十分鐘過去了,你見他還沒來,你想都等了這么久了還不來,那你還是先去吃飯好了,
這時你還是執行緒t1,你改bug的同事是執行緒t2,t2讓t1等待了指定時間,此時t1等待期間就屬于TIMED_WATING狀態,
t1等待10分鐘后,就自動喚醒,擁有了去爭奪鎖的資格,

TERMINATED狀態

終止狀態,執行緒已執行完畢,

執行緒狀態轉換

上面講解了執行緒各個狀態的相關知識,下面我們繼續講執行緒狀態是如何轉換的,先看下面的圖:
在這里插入圖片描述

BLOCKED與RUNNABLE狀態的轉換

上面說過處于BLOCKED狀態的執行緒是因為在等待鎖的釋放,假如這里有兩個執行緒a和b,a執行緒提前獲得了鎖并且暫未釋放鎖,此時b就處于BLOCKED狀態,看一個例子:

@Test
public void blockedTest() {

    Thread a = new Thread(new Runnable() {
        @Override
        public void run() {
            testMethod();
        }
    }, "a");
    Thread b = new Thread(new Runnable() {
        @Override
        public void run() {
            testMethod();
        }
    }, "b");

    a.start();
    b.start();
    System.out.println(a.getName() + ":" + a.getState()); // 輸出?
    System.out.println(b.getName() + ":" + b.getState()); // 輸出?
}

// 同步方法爭奪鎖
private synchronized void testMethod() {
    try {
        Thread.sleep(2000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

初看之下,大家可能會覺得執行緒a會先呼叫同步方法,同步方法內又呼叫了Thread.sleep()方法,必然會輸出TIMED_WAITING,而執行緒b因為等待執行緒a釋放鎖所以必然會輸出BLOCKED,

其實不然,有兩點需要值得大家注意,一是在測驗方法blockedTest()內還有一個main執行緒,二是啟動執行緒后執行run方法還是需要消耗一定時間的,

測驗方法的main執行緒只保證了a,b兩個執行緒呼叫start()方法(轉化為RUNNABLE狀態),如果CPU執行效率高一點,還沒等兩個執行緒真正開始爭奪鎖,就已經列印此時兩個執行緒的狀態(RUNNABLE)了,

當然,如果CPU執行效率低一點,其中某個執行緒也是可能列印出BLOCKED狀態的(此時兩個執行緒已經開始爭奪鎖了),

那我想要列印出BLOCKED狀態該怎么處理呢?BLOCKED狀態的產生需要兩個執行緒爭奪鎖才行,那我們處理下測驗方法里的main執行緒就可以了,讓它“休息一會兒”,呼叫一下Thread.sleep()方法,

需要注意的是main執行緒休息的時間,要保證在執行緒爭奪鎖的時間內,不要等到前一個執行緒鎖都釋放了你再去爭奪鎖,此時還是得不到BLOCKED狀態的,
把上面的代碼稍稍修改下:

public void blockedTest() throws InterruptedException {
    ······
    a.start();
    Thread.sleep(1000L); // 需要注意這里main執行緒休眠了1000毫秒,而testMethod()里休眠了2000毫秒
    b.start();
    System.out.println(a.getName() + ":" + a.getState()); // 輸出?
    System.out.println(b.getName() + ":" + b.getState()); // 輸出?
}

修改了以后兩個執行緒的狀態轉換如下

  • a的狀態轉換程序:RUNNABLE(a.start()) -> TIMED_WATING(Thread.sleep())->RUNABLE(sleep()時間到)->BLOCKED(未搶到鎖) -> TERMINATED
  • b的狀態轉換程序:RUNNABLE(b.start()) -> BLOCKED(未搶到鎖) ->TERMINATED

斜體表示可能出現的狀態, 大家可以在自己的電腦上多試幾次看看輸出,同樣,這里的輸出也可能有多鐘結果,

WAITING狀態與RUNNABLE狀態的轉換\

根據轉換圖我們知道有3個方法可以使執行緒從RUNNABLE狀態轉為WAITING狀態,這里主要介紹下Object.wait()和Thread.join(),

Object.wait()方法

呼叫wait()方法前執行緒必須持有物件的鎖,

執行緒呼叫wait()方法時,會釋放當前的鎖,直到有其他執行緒呼叫notify()/notifyAll()方法喚醒等待鎖的執行緒,

需要注意的是,其他執行緒呼叫notify()方法只會喚醒單個等待鎖的執行緒,如有有多個執行緒都在等待這個鎖的話不一定會喚醒到之前呼叫wait()方法的執行緒,

同樣,呼叫notifyAll()方法喚醒所有等待鎖的執行緒之后,也不一定會馬上把時間片分給剛才放棄鎖的那個執行緒,具體要看系統的調度,

Thread.join()

呼叫join()方法不會釋放鎖,會一直等待當前執行緒執行完畢(轉換為TERMINATED狀態),
修改下上面的代碼繼續距離 eg.

public void blockedTest() {
    ······
    a.start();
    a.join();
    b.start();
    System.out.println(a.getName() + ":" + a.getState()); // 輸出 TERMINATED
    System.out.println(b.getName() + ":" + b.getState());
}

要是沒有呼叫join方法,main執行緒不管a執行緒是否執行完畢都會繼續往下走,

a執行緒啟動之后馬上呼叫了join方法,這里main執行緒就會等到a執行緒執行完畢,所以這里a執行緒列印的狀態固定是TERMINATED,

至于b執行緒的狀態,有可能列印RUNNABLE(尚未進入同步方法),也有可能列印TIMED_WAITING(進入了同步方法)

TIMED_WAITING與RUNNABLE狀態轉換

TIMED_WAITING與WAITING狀態類似,只是TIMED_WAITING狀態等待的時間是指定的,

Thread.sleep(long)

使當前執行緒睡眠指定時間,需要注意這里的“睡眠”只是暫時使執行緒停止執行,并不會釋放鎖,時間到后,執行緒會重新進入RUNNABLE狀態,

Object.wait(long)

wait(long)方法使執行緒進入TIMED_WAITING狀態,這里的wait(long)方法與無參方法wait()相同的地方是,都可以通過其他執行緒呼叫notify()或notifyAll()方法來喚醒,

不同的地方是,有參方法wait(long)就算其他執行緒不來喚醒它,經過指定時間long之后它會自動喚醒,擁有去爭奪鎖的資格,

Thread.join(long)

join(long)使當前執行緒執行指定時間,并且使執行緒進入TIMED_WAITING狀態,

繼續改上面的示例:

public void blockedTest() {
    ······
    a.start();
    a.join(1000L);
    b.start();
    System.out.println(a.getName() + ":" + a.getState()); // 輸出 TIEMD_WAITING
    System.out.println(b.getName() + ":" + b.getState());
}

這里呼叫a.join(1000L),因為是指定了具體a執行緒執行的時間的,并且執行時間是小于a執行緒sleep的時間,所以a執行緒狀態輸出TIMED_WAITING,

b執行緒狀態仍然不固定(RUNNABLE或BLOCKED),

執行緒中斷

在某些情況下,我們在執行緒啟動后發現并不需要它繼續執行下去時,需要中斷執行緒,目前在Java里還沒有 安全直接的方法來停止執行緒,但是Java提供了執行緒中斷機制來處理需要中斷執行緒的情況,

執行緒中斷機制是一種協作機制,需要注意,通過中斷操作并不能直接終止一個執行緒,而是通知需要被中斷的執行緒自行處理,
簡單介紹下Thread類里提供的關于執行緒中斷的幾個方法:

  • Thread.interrupt():中斷執行緒,這里的中斷執行緒并不會立即停止執行緒,而是設定執行緒的中斷狀態為true(默認是flase);
  • Thread.interrupted():測驗當前執行緒是否被中斷,執行緒的中斷狀態受這個方法的影響,意思是呼叫一次使執行緒中斷狀態設定為true,連續呼叫兩次會使得這個執行緒的中斷狀態重新轉為false;
  • Thread.isInterrupted():測驗當前執行緒是否被中斷,與上面方法不同的是呼叫這個方法并不會影響執行緒的中斷狀態,

在執行緒中斷機制里,當其他執行緒通知需要被中斷的執行緒后,執行緒中斷的狀態被設定為true,但是具體被要求中斷的執行緒要怎么處理,完全由被中斷執行緒自己而定,可以在合適的時候處理中斷請求,也可以完全不處理繼續執行下去,

講到這里本章對多執行緒系列之執行緒狀態和主要轉換方法的講解也就結束了,如果想了解更多知識可以在對應的專欄中看系列文章,謝謝大家的觀看,希望能給各位同學帶來幫助,如果覺得博主寫的還可以的,可以點贊收藏, 😉

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/240847.html

標籤:其他

上一篇:【Linux】網路編程套接字(一)—— UDP編程

下一篇:云計算1+X平臺運維與開發認證能(初級)選擇題

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more