主頁 > 軟體設計 > Nachos實驗實作執行緒id、限制執行緒數和更改調度演算法(按優先級調度)

Nachos實驗實作執行緒id、限制執行緒數和更改調度演算法(按優先級調度)

2020-11-19 12:59:09 軟體設計

Nachos實驗1實作執行緒id、限制執行緒數和更改調度演算法(按優先級調度)

一、理解Nachos執行緒的運行及調度原理

Nachos實驗主要是為了使我們深入的理解作業系統結構,Nachos也是一個作業系統,但是它很簡便,我們可以很容易的對它進行改動;通過對Nachos的實驗來增加我們對作業系統的理解,當前這個實驗主要是通過我們實作Nachos執行緒id和優先級調度來對作業系統行程和執行緒的理解,Nachos里面主要分為內核執行緒(例如main執行緒)和用戶執行緒,主要通過主執行緒來操作,例如新建和調度執行緒,其實對于增加執行緒id和限制最大執行緒數,只要了解行程的實作原理,看代碼也會非常的容易理解,這樣就會非常簡單了,
對于理解這次實驗代碼,我認為,需要看thread.h、thread.cc、scheduler.h、scheduler.cc、List.h、List.cc、main.h、main.cc,對于main.h和main.cc,只需要知道在運行Nachos的時候加-K命令(“./nachos -K”)就會進入執行緒測驗就行了,

二、增加執行緒ID和最大執行緒數

在增加實作執行緒id和最大執行緒數時,thread類的建構式盡量不要改動,只需再重構一個構造方法,因為之前的建構式可能在Nachos的其他類里會呼叫它,所以我們不能再之前的建構式里構造,這樣才不會打亂原系統的正確性,所以需要增加一個建構式Thread(char* debugName,int priority);至于int priority先不用管,這是之后優先級調度需要用到的引數,不影響我們使用這個建構式

1.增改class thread,增加執行緒id成員和一些需要用到的成員方法

#define MAX_SIZE  128//最大執行緒數
//pk陣列主要記錄執行緒號被使用的狀態
//下標位執行緒號,陣列對應值位執行緒號狀態
//對應值為0時,表示該執行緒號沒有執行緒占用
//對應值為1時,表示該執行緒號被占用
static int pk[MAX_SIZE]={0};
static int threadMAX = 0;//記錄執行緒數

class Thread {
  private:
    // NOTE: DO NOT CHANGE the order of these first two members.
    // THEY MUST be in this position for SWITCH to work.
    int *stackTop;			 // the current stack pointer
    void *machineState[MachineStateSize];  // all registers except for stackTop

	int tid;
  public:
    Thread(char* debugName);//原建構式		// initialize a Thread 
    ~Thread(); //解構式				// deallocate a Thread
					// NOTE -- thread being deleted
					// must not be running when delete 
					// is called

    // basic thread operations
	Thread(char* debugName,int priority);//新建構式
	int getTid(){return this->tid;};//獲得執行緒id

    void Fork(VoidFunctionPtr func, void *arg); //將執行緒加入就緒佇列
    				// Make thread run (*func)(arg)
    void Yield();  //打斷當前執行緒,運行就緒佇列里的執行緒
					// Relinquish the CPU if any 
				// other thread is runnable
    void Sleep(bool finishing);//將當前執行緒阻塞
								 // Put the thread to sleep and 
				// relinquish the processor
    void Begin();	// Startup code for the thread	
    void Finish();  //執行緒運行結束	
						// The thread is done executing
    
    void CheckOverflow();   	// Check if thread stack has overflowed
    void setStatus(ThreadStatus st) { status = st; }//設定執行緒狀態
    char* getName() { return (name); }//獲取執行緒名字
    void Print() { cout << name; }//列印執行緒名字
    void SelfTest();	//測驗方法	// test whether thread impl is working

  private:
    // some of the private data for this class is listed above
    
    int *stack; 	 	// Bottom of the stack 
				// NULL if this is the main thread
				// (If NULL, don't deallocate stack)
    ThreadStatus status;	// ready, running or blocked
    char* name;

    void StackAllocate(VoidFunctionPtr func, void *arg);
    				// Allocate a stack for thread.
				// Used internally by Fork()

// A thread running a user program actually has *two* sets of CPU registers -- 
// one for its state while executing user code, one for its state 
// while executing kernel code.

    int userRegisters[NumTotalRegs];	// user-level CPU register state

  public:
    void SaveUserState();		// save user-level register state
    void RestoreUserState();		// restore user-level register state

    AddrSpace *space;			// User code this thread is running.
};

2.在thread.cc里面增加我們需要的功能,切記,我們是新增建構式,不是在原建構式更改!!

Thread::Thread(char* threadName)//原建構式,不要更改它
{
    name = threadName;
    stackTop = NULL;
    stack = NULL;
    status = JUST_CREATED;
    for (int i = 0; i < MachineStateSize; i++) {
	machineState[i] = NULL;		// not strictly necessary, since
					// new thread ignores contents 
					// of machine registers
    }
    space = NULL;
}
Thread::Thread(char* threadName,int priority)//新建構式
{

	if(++threadMAX > MAX_SIZE){//限制執行緒數
		cout<<"最大執行緒數:"<<MAX_SIZE<<"!!!"<<endl;
		ASSERT(threadMAX<=MAX_SIZE);
	}
	int j;
	for(j=0;j<MAX_SIZE;j++){//設定id
		if(pk[j]==0){
			this->tid = j+1;
			pk[j] = 1;
			break;
		}
	}

    name = threadName;
    stackTop = NULL;
    stack = NULL;
    status = JUST_CREATED;
    for (int i = 0; i < MachineStateSize; i++) {
    machineState[i] = NULL;     // not strictly necessary, since
                    // new thread ignores contents 
                    // of machine registers
    }
    space = NULL;
}

3.增改解構式

Thread::~Thread()
{
    DEBUG(dbgThread, "Deleting thread: " << name);
	pk[tid -1] = 0;//執行緒id撤銷
	threadMAX--;//執行緒數減一
    ASSERT(this != kernel->currentThread);
    if (stack != NULL)
	DeallocBoundedArray((char *) stack, StackSize * sizeof(int));
}

4.在測驗函式增改測驗代碼

void Thread::SelfTest()
{
    DEBUG(dbgThread, "Entering Thread::SelfTest");

    /*Thread *t = new Thread("forked thread");

    t->Fork((VoidFunctionPtr) SimpleThread, (void *) 1);
    kernel->currentThread->Yield();
    SimpleThread(0);*/

	Thread *t[130];
	for(int i = 0;i < 130;i++){
		t[i] = new Thread("執行緒",1);
		cout<<t[i]->getName()<<t[i]->getTid()<<endl;
	}
}

測驗

make
./nachos -K

編譯
測驗

結果


在這里插入圖片描述
實作執行緒id和限制最大數的所有增改原始碼thread.h和thread.cc,下載鏈接:下載

三、實作更改Nachos執行緒調度,按優先級調度

對于按優先級調度,我的想法是,因為創建一個執行緒之后,需要加入就緒佇列就能運行,Fork方法就實作了將執行緒(readyList)加入就緒佇列里的功能,還有Yield方法的功能是打斷當前正在運行的執行緒,運行就緒佇列里的執行緒,再將被打斷的執行緒加入就緒佇列,而加入就緒佇列是呼叫的是Schedule類里的ReadyToRun(Thread *thread)方法,ReadyToRun方法實作了將執行緒加入在就緒佇列里的隊尾,就是一個先進先調度的調度機制,我經歷了無數次錯誤之后,最后把思想集中在了加入就緒佇列時按照執行緒優先級加入佇列,實作如下(這是接著之前執行緒id做的):
1.增改thread.h檔案,增加優先級成員

#define MAX_SIZE  128  //最大執行緒數
//pk陣列主要記錄執行緒號被使用的狀態
//下標位執行緒號,陣列對應值位執行緒號狀態
//對應值為0時,表示該執行緒號沒有執行緒占用
//對應值為1時,表示該執行緒號被占用
static int pk[MAX_SIZE]={0};
static int threadMAX = 0;//記錄執行緒數

class Thread {
  private:
    // NOTE: DO NOT CHANGE the order of these first two members.
    // THEY MUST be in this position for SWITCH to work.
    int *stackTop;			 // the current stack pointer
    void *machineState[MachineStateSize];  // all registers except for stackTop

	int tid;//執行緒id
	int priority;//執行緒優先級,值越大優先級越高
  public:
    Thread(char* debugName);//原建構式		// initialize a Thread 
    ~Thread(); //解構式				// deallocate a Thread
					// NOTE -- thread being deleted
					// must not be running when delete 
					// is called

    // basic thread operations
	Thread(char* debugName,int priority);//新建構式
	int getTid(){return this->tid;};//獲得執行緒id
	int getPriority(){return priority;};//獲得執行緒優先級


    void Fork(VoidFunctionPtr func, void *arg); //將執行緒加入就緒佇列
    				// Make thread run (*func)(arg)
    void Yield();  //打斷當前執行緒,運行就緒佇列里的執行緒
					// Relinquish the CPU if any 
				// other thread is runnable
    void Sleep(bool finishing);//將當前執行緒阻塞
								 // Put the thread to sleep and 
				// relinquish the processor
    void Begin();	// Startup code for the thread	
    void Finish();  //執行緒運行結束	
						// The thread is done executing
    
    void CheckOverflow();   	// Check if thread stack has overflowed
    void setStatus(ThreadStatus st) { status = st; }//設定執行緒狀態
    char* getName() { return (name); }//獲取執行緒名字
    void Print() { cout << name; }//列印執行緒名字
    void SelfTest();	//測驗方法	// test whether thread impl is working

  private:
    // some of the private data for this class is listed above
    
    int *stack; 	 	// Bottom of the stack 
				// NULL if this is the main thread
				// (If NULL, don't deallocate stack)
    ThreadStatus status;	// ready, running or blocked
    char* name;

    void StackAllocate(VoidFunctionPtr func, void *arg);
    				// Allocate a stack for thread.
				// Used internally by Fork()

// A thread running a user program actually has *two* sets of CPU registers -- 
// one for its state while executing user code, one for its state 
// while executing kernel code.

    int userRegisters[NumTotalRegs];	// user-level CPU register state

  public:
    void SaveUserState();		// save user-level register state
    void RestoreUserState();		// restore user-level register state

    AddrSpace *space;			// User code this thread is running.
};

2.增改thread.cc檔案

Thread::Thread(char* threadName)//內核執行緒創建
{   int j;
    for(j=0;j<2;j++){//設定id
        if(pk[j]==0){
            this->tid = j-1;
            pk[j] = 1;
            break;
        }
    }

    priority = 100000;
    name = threadName;
    stackTop = NULL;
    stack = NULL;
    status = JUST_CREATED;
    for (int i = 0; i < MachineStateSize; i++) {
    machineState[i] = NULL;     // not strictly necessary, since
                    // new thread ignores contents 
                    // of machine registers
    }
    space = NULL;
}

Thread::Thread(char* threadName,int priority)
{

	if(++threadMAX > MAX_SIZE){//限制執行緒數
		cout<<"最大執行緒數:"<<MAX_SIZE<<"!!!"<<endl;
		ASSERT(threadMAX<=MAX_SIZE);
	}
	int j;
	for(j=2;j<MAX_SIZE;j++){//設定id
		if(pk[j]==0){
			this->tid = j-1;
			pk[j] = 1;
			break;
		}
	}
	this->priority = priority;
    name = threadName;
    stackTop = NULL;
    stack = NULL;
    status = JUST_CREATED;
    for (int i = 0; i < MachineStateSize; i++) {
    machineState[i] = NULL;     // not strictly necessary, since
                    // new thread ignores contents 
                    // of machine registers
    }
    space = NULL;
}

Thread::~Thread()
{
    DEBUG(dbgThread, "Deleting thread: " << name);
    pk[tid + 1] = 0;
    threadMAX--;
    ASSERT(this != kernel->currentThread);
    if (stack != NULL)
    DeallocBoundedArray((char *) stack, StackSize * sizeof(int));
}

3.增改List.h檔案,增加成員方法


template <class T>
class List {
  public:
    List();			// initialize the list
    virtual ~List();		// de-allocate the list

    virtual void Prepend(T item);// Put item at the beginning of the list
    virtual void Append(T item); // Put item at the end of the list

    T Front() { return first->item; }
    				// Return first item on list
				// without removing it
    T RemoveFront(); 		// Take item off the front of the list
    void Remove(T item); 	// Remove specific item from list

    bool IsInList(T item) const;// is the item in the list?

    unsigned int NumInList() { return numInList;};
    				// how many items in the list?
    bool IsEmpty() { return (numInList == 0); };
    				// is the list empty? 

    void Apply(void (*f)(T)) const; 
    				// apply function to all elements in list

    virtual void SanityCheck() const;	
				// has this list been corrupted?
    void SelfTest(T *p, int numEntries);
				// verify module is working

	void setNumInList(int numInList){this->numInList = numInList;}//設定佇列元素個數
	ListElement<T>* getfirst(){return first;};//get頭指標
	ListElement<T>* getlast(){return last;};//get尾指標
	void setfirst(ListElement<T> *first){this->first = first;};//設定頭結點
	void setlast(ListElement<T>* last){this->last = last;};//設定尾結點
  protected:
    ListElement<T> *first;  	// Head of the list, NULL if list is empty
    ListElement<T> *last;	// Last element of list
    int numInList;		// number of elements in list

    friend class ListIterator<T>;
};

4.增改schedule.h檔案,增加成員方法


class Scheduler {
  public:
    Scheduler();		// Initialize list of ready threads 
    ~Scheduler();		// De-allocate ready list

    void ReadyToRun(Thread* thread);	
    				// Thread can be dispatched.
    Thread* FindNextToRun();	// Dequeue first thread on the ready 
				// list, if any, and return thread.
    void Run(Thread* nextThread, bool finishing);
    				// Cause nextThread to start running
    void CheckToBeDestroyed();// Check if thread that had been
    				// running needs to be deleted
    void Print();		// Print contents of ready list
    
    // SelfTest for scheduler is implemented in class Thread
	
	void ReadyToRunPriority(Thread* thread); //將執行緒按優先級加入就緒佇列    
  private:
    List<Thread *> *readyList;  // queue of threads that are ready to run,
				// but not running
    Thread *toBeDestroyed;	// finishing thread to be destroyed
    				// by the next thread that runs
};

5.增改schedule.cc檔案(實作ReadyToRunPriority方法)

void Scheduler::ReadyToRunPriority(Thread *thread){
	//將執行緒thread按優先級加入就緒佇列
	ASSERT(kernel->interrupt->getLevel() == IntOff);
	DEBUG(dbgThread, "Putting thread on ready list: " << thread->getName());
	thread->setStatus(READY);

	ASSERT(!readyList->IsInList(thread));//斷言
	ListElement<Thread *> *element = new ListElement<Thread *>(thread);//創建新結點
	if(readyList->IsEmpty()){
		//當就緒佇列為空時,直接加入佇列
		readyList->setfirst(element);
		readyList->setlast(element);
		readyList->setNumInList(readyList->NumInList()+1);
	}else{
		//遍歷就緒佇列
		//當執行緒優先級大于就緒佇列結點所對應執行緒優先級時
		//將element插入在所對應結點之前
		if(thread->getPriority() > readyList->getfirst()->item->getPriority()){
			element->next = readyList->getfirst();
			readyList->setfirst(element);
			readyList->setNumInList(readyList->NumInList()+1); 
		}else{
			ListElement<Thread *> *pre = readyList->getfirst(); 
			ListElement<Thread *> *ptr = pre->next;
			while(ptr != NULL){
				if(thread->getPriority() > ptr->item->getPriority()){
					element->next = ptr;
					pre->next = element;
					readyList->setNumInList(readyList->NumInList()+1); 
					break;
				}else{
					pre = ptr;
					ptr = ptr->next;
				}
			}
			if(ptr == NULL){
				element->next = NULL;
				pre->next = element;
				readyList->setlast(element);
				readyList->setNumInList(readyList->NumInList()+1); 
			}
		}
	}
}

6.在thread.cc里更改Fork方法

void
Thread::Fork(VoidFunctionPtr func, void *arg)
{
    Interrupt *interrupt = kernel->interrupt;
    Scheduler *scheduler = kernel->scheduler;
    IntStatus oldLevel;

    DEBUG(dbgThread, "Forking thread: " << name << " f(a): " << (int) func << " " << arg);

    StackAllocate(func, arg);

    oldLevel = interrupt->SetLevel(IntOff);
    scheduler->ReadyToRunPriority(this);//將執行緒按優先級加入就緒佇列
                                    // ReadyToRun assumes that interrupts 
                    // are disabled!
    (void) interrupt->SetLevel(oldLevel);
}

7.在thread.cc里增改Yield方法

void
Thread::Yield ()
{
    Thread *nextThread;
    IntStatus oldLevel = kernel->interrupt->SetLevel(IntOff);

    ASSERT(this == kernel->currentThread);

    DEBUG(dbgThread, "Yielding thread: " << name);

    /*nextThread = kernel->scheduler->FindNextToRun();
    if (nextThread != NULL) {
    kernel->scheduler->ReadyToRun(this);
    kernel->scheduler->Run(nextThread, FALSE);
    }*/
    kernel->scheduler->ReadyToRunPriority(this);//將當前執行緒按優先級加入就緒佇列
    nextThread = kernel->scheduler->FindNextToRun();
    if (nextThread != NULL) {
    kernel->scheduler->Run(nextThread, FALSE);
    }
    (void) kernel->interrupt->SetLevel(oldLevel);
}


7.在thread.cc里增改SimpleThread方法(可改可不改)

static void
SimpleThread(int which)
{
    int num;

    for (num = 0; num < 4; num++) {

    cout << "*** thread " << which<< " looped " << num << " times\n";
        kernel->currentThread->Yield();
    }
    //kernel->currentThread->Yield();

}


8.在thread.cc里增改測驗方法
下面會用到C語言函式庫的srand()和time()函式,需要增加頭檔案#include “time.h"和#include"stdlib.h”,記得加上去,不然會報錯

void
Thread::SelfTest()
{
    DEBUG(dbgThread, "Entering Thread::SelfTest");

    /*Thread *t = new Thread("forked thread");

    t->Fork((VoidFunctionPtr) SimpleThread, (void *) 1);
    kernel->currentThread->Yield();
    SimpleThread(0);*/

/*  Thread *t[130];
    for(int i = 0;i < 130;i++){
        t[i] = new Thread("執行緒",1);
        cout<<t[i]->getName()<<t[i]->getTid()<<endl;
    }*/

     Thread *t[4];
    for(int i = 0;i < 4;i++){
        srand(time(NULL)+i);
        t[i] = new Thread("執行緒",rand()%10+1);
        cout<<t[i]->getName()<<threadMAX<<" tid:"<<t[i]->getTid()<<" priority:"<<t[i]->getPriority()<<endl;
        t[i]->Fork((VoidFunctionPtr) SimpleThread, (void *)threadMAX);
    }



}

測驗
在這里插入圖片描述

本次Nachos實驗實作的所有增改原始碼的所有原始碼,下載鏈接:下載

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

標籤:其他

上一篇:停一停先別劃走!吊打全網的MySQL進階面試突擊,吃透最少阿里P7

下一篇:搜外七巧板-小程式開發者接入

標籤雲
其他(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