深入淺出多執行緒系列之二 關於Thread的那些事

2021-09-06 03:26:25 字數 3477 閱讀 5197

1:你可以呼叫執行緒的例項方法join來等待乙個執行緒的結束。例如:

public

static

void

mainthread()

static

void

go()

在列印了

1000個y

之後,後面就會輸出

」thread t has ended!」.,

你可以在呼叫

join

方法的時候給它乙個

timeout

的引數,例如要超時一秒:

t.join(

1000

);t.join(timespan.fromseconds(

1));

2:為執行緒傳遞引數

為執行緒傳遞引數的最簡單的方法莫過於執行乙個

lambda

表示式,然後在方法裡面給引數了,例如:

static

void

main()

static

void

print(

string

message)

使用這種方法,你可以傳遞任何引數。

當然thread的建構函式中有乙個傳遞引數的版本,你也可以使用下面的**來傳遞引數:

static

void

main()

static

void

print(

object

messageobj)

這裡有一點要注意,因為

print

的方法簽名必須匹配

parameterizedthreadstart

委託,

而parameterizedthreadstart

的引數是

object

,所以print

的引數必須也是

object

,所以在

print

方法中必須進行強制轉換。

3:lambda和捕獲的變數。

考慮下下面的**:

for(inti =

0; i 

<

10; i++)

實際的輸出是不確定的,例如可能是

0113348899.

為什麼???

關鍵的問題是區域性變數i在for迴圈中指向的是相同的記憶體位址.因此,每一次都在乙個執行時會被改變值的變數(i)上呼叫console.write方法,

在foreach中也存在相同問題。

解決這個問題的方法很簡單,例如使用乙個臨時的變數。例如:

for(inti =

0; i 

<

10; i++)

因為i是值型別,所以int temp=i 會複製i的值給temp,而在for迴圈中temp變數都是不同的,所以可以解決這個問題。

下面的也是同樣的道理:

for(inti =

0; i 

<

10; i++)

下面的例子可能更明顯一些:

string

text ="

t1";thread t1 

=new

thread(() 

=>

console.writeline(text));

text ="

t2";thread t2 

=new

thread(() 

=>

console.writeline(text));

t1.start();

t2.start();

因為兩個

lambda

表示式捕獲的是相同的

text

變數,所以

「t2」

會被列印兩次。

output:

t2t2

4:命名執行緒:

但是你只能設定一次執行緒的名字,嘗試在以後更改名字會丟擲乙個異常,為變數命名的使用的是name屬性,例如:

thread worker

=new

thread(go);

worker.name

=」worker」;

worker.name

=」worker」; 

//會丟擲異常

5 :前台執行緒和後台執行緒:

預設你顯示建立的執行緒都是前台執行緒。

只要前台執行緒有乙個還在執行,應用程式就不會結束。

只有所有的前台執行緒都結束了,應用程式才會結束,

在應用程式結束的時候,所有後台執行緒都會被終止。

你可以通過執行緒的

isbackground

屬性來查詢和更改執行緒的狀態。這裡是乙個例子。

static

void

main(

string

args) 如果

args.length>0

,則worker

就是後台執行緒,那麼應用程式會立即終止。

否則worker

預設就是前台執行緒,所以只有在

console.readline()

方法結束後,應用程式才會終止。

所以當你有時候發現關閉了應用程式視窗,但是在任務管理器中應用程式仍然在執行,很有可能就是還有一些前台執行緒在執行。

6: 執行緒的優先順序:

enum threadpriority

只有在多個執行緒的環境下,執行緒優先順序才有用。

把乙個執行緒的優先順序提高並不會提高實時系統的效能,因為程序的優先順序才是應用程式的瓶頸。為了更好的實時工作,你必須提高程序的優先順序。

例如process.priorityclass=processpriorityclass.high.

7: 異常捕獲:

嘗試在乙個執行緒中捕獲另乙個執行緒的異常時失敗的。例如:

public

static

void

main()

catch

(exception ex)

}static

void

go() 

我們在另乙個執行緒中丟擲了異常

(throw null;),

然後嘗試在主線程中捕獲它,我們永遠都不到這個異常。

為了在另乙個執行緒中捕獲異常,必須在那個執行緒上

try,catch,finally.

所以可以將**改為下面的方式:

public

static

void

main()

static

void

go()

catch

(exception ex)}

8:全域性捕獲異常:

事件和事件都只有在主

ui執行緒中丟擲異常的時候才會被觸發。

為了捕獲所有的未處理的異常,你可以使用

雖然這個事件在任何未處理異常丟擲的時候都會被觸發,但是它不能讓你阻止應用程式的關閉。

深入淺出多執行緒系列之二 關於Thread的那些事

1 你可以呼叫執行緒的例項方法join來等待乙個執行緒的結束。例如 public static void mainthread static void go 在列印了 1000個y 之後,後面就會輸出 thread t has ended 你可以在呼叫 join 方法的時候給它乙個 timeout ...

深入淺出多執行緒系列之三 執行緒池

執行緒池 每乙個執行緒缺省會被分配 1mb的記憶體,在 c 中,這些都是實打實的分配的,當乙個執行緒啟動的時候,為了分配臨時堆疊大約需要花費幾百微秒的時間。執行緒池通過迴圈利用執行緒可以讓你更高效的利用執行緒。執行緒池就像外包的勞務隊一樣,有任務給他們,他們會管理勞務工的一切,你不需要去花時間去找單...

深入淺出多執行緒系列之三 執行緒池

執行緒池 每乙個執行緒缺省會被分配 1mb的記憶體,在 c 中,這些都是實打實的分配的,當乙個執行緒啟動的時候,為了分配臨時堆疊大約需要花費幾百微秒的時間。執行緒池通過迴圈利用執行緒可以讓你更高效的利用執行緒。執行緒池就像外包的勞務隊一樣,有任務給他們,他們會管理勞務工的一切,你不需要去花時間去找單...