国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

Java基礎 獲取java線程中信息的兩種方法

2019-11-17 04:34:45
字體:
供稿:網(wǎng)友
在進行多線程編程中,比較重要也是比較困難的一個操作就是如何獲取線程中的信息。大多數(shù)人會采取比較常見的一種方法就是將線程中要返回的結(jié)果存儲在一個字段中,然后再提供一個獲取方法將這個字段的內(nèi)容返回給該方法的調(diào)用者。如以下的ReturnThreadInfo類:

package threadtest1;

/**

*

* @author shi mingxiang

*/

public class ReturnThreadInfo extends Thread {

PRivate String str;

public ReturnThreadInfo() {

this.str = "Hello";

}

public void run(){

this.str = "Hello World!";

}

public String getThreadInfo(){

return this.str;

}

}

大家可以看到該類是一個線程類并含有一個初始值為"Hello"的字段str以及一個可以返回str值的方法:getThreadInfo(),而且當這個線程啟動后str會被賦于新值:"Hello World!"。現(xiàn)在我想在另外一個類中啟動ReturnThreadInfo線程,并通過getThreadInfo()方法獲取值為"Hello World!"的變量并打印輸出到控制臺中。以下給出一個實現(xiàn)該功能的Main類:

package threadtest1;

/**

*

* @author shi mingxiang

*/

public class Main{

public Main() {

}

/**

* @param args the command line arguments

*/

public static void main(String[] args) {

ReturnThreadInfo returnThreadInfo = new ReturnThreadInfo();

returnThreadInfo.start();//創(chuàng)建并啟動ReturnThreadInfo線程

System.out.println(returnThreadInfo.getThreadInfo());//獲取并輸出returnThreadInfo對象的str的值

}

}

以上是一個多數(shù)熟悉單線程編程的人在第一反應下給出的實現(xiàn)方法。但是該類在運行的時候輸出的結(jié)果卻不是期望的"Hello World!"而是"Hello",這是由于線程的競爭條件導致的(由于ReturnThreadInfo線程和Main線程的優(yōu)先級都為5,所以在很大幾率上ReturnThreadInfo線程的run()方法還沒有運行,Main類就已經(jīng)運行System.out.println(returnThreadInfo.getThreadInfo());將"Hello"輸出了。具體的原理可以參見另一篇文章:"java多線程的幾點誤區(qū)")。有的人可能會立即想到把ReturnThreadInfo線程的優(yōu)先級設高些(比如最大的10)就可以returnThreadInfo線程的run()方法先運行完,然后Main類的System.out.println(returnThreadInfo.getThreadInfo())再運行,這樣輸出的結(jié)就一定是期望的"Hello World!"了。這種通過調(diào)整線程優(yōu)先級的方法固然可以在某種程度上解決該問題,但是線程爭用CPU運行時間的原理卻決不僅僅只是優(yōu)先級高低的原因(優(yōu)先級高的線程并不意味著一定比優(yōu)先級低的線程先運行,只是幾率要更大一些)。你并不希望ReturnThreadInfo線程9999次都比Main先運行,卻在最關鍵的一次在Main之后再運行。因此下面給出兩種比較常見的獲取線程信息的方法:

一、輪詢

比較常見的一種解決方案是,讓線程類獲取方法在結(jié)果字段設置之前返回一個標志值。然后主線程定時詢問獲取方法,看是否返回了標志之外的值。以下給出了具體的實現(xiàn)方法,該方法不斷測試str的值是否為"Hello",如果不為"Hello"才打印輸出它。例如:

package threadtest1;

/**

*

* @author shi mingxiang

*/

public class Main{

public Main() {

}

/**

* @param args the command line arguments

*/

public static void main(String[] args) {

ReturnThreadInfo returnThreadInfo = new ReturnThreadInfo();

returnThreadInfo.start();//創(chuàng)建并啟動ReturnThreadInfo線程

while(true){

String str = returnThreadInfo.getThreadInfo();

if(!str.equals("Hello")){

System.out.println(returnThreadInfo.getThreadInfo());

break;

}

}

}

}

這種方案雖然能起到作用,但是它做了大量不需要做的工作。事實上,還有一種更簡單有效的方法來解決這個問題。

二、回調(diào)

輪詢方法最大的特點是主類Main不斷詢問線程類是否結(jié)束,這實際上大量浪費了運行時間,特別是當線程特別多的時候。因此如果反過來在線程結(jié)束時,由線程自己告訴主類Main線程已經(jīng)結(jié)束,然后Main再獲取并輸出str的值,這樣就避免了輪詢方法所帶來的不必要的系統(tǒng)開銷問題。

在具體的實現(xiàn)過程中,線程可以在結(jié)束時通過調(diào)用主類中的一個方法來實現(xiàn)告知功能,這種方法叫做回調(diào)。這樣主類Main就可以在等待線程結(jié)束時休息,也就不會占用運行線程的時間。下面是修改后的Main類:

public class Main{

public Main() {

}

/**

* @param args the command line arguments

*/

public static void main(String[] args) {

// TODO code application logic here

ReturnThreadInfo returnThreadInfo = new ReturnThreadInfo();

returnThreadInfo.start();

}

public static void receiveStr(String str){

System.out.println(str);

}

}

相比于前面,我們在Main類中添加了一個靜態(tài)方法receiveStr(String str),該方法是供線程結(jié)束之前調(diào)用,通過參數(shù)str將要返回的線程信息返回給Main類并輸出顯示出來。下面是修改后的ReturnThreadInfo類,該類在線程結(jié)束前回調(diào)了Main.receiveStr方法,通知線程已結(jié)束。

package threadtest1;

/**

*

* @author shi mingxiang

*/

public class ReturnThreadInfo extends Thread {

private String str;

public ReturnThreadInfo() {

this.str = "Hello";

}

public void run(){

this.str = "Hello World!";

Main.receiveStr(str); //回調(diào)receiveStr方法

}

}

如果有很多個對象關心線程的返回的信息,線程可以保存一個回調(diào)對象列表。某個對象可以通過已經(jīng)定義的一個對象將自己添加到列表中,表示自己對這些信息的關注。如果有多個類的實例關心這些信息,也可以定義一個interface,在interface中聲名回調(diào)方法,然后這些類都實現(xiàn)這個接口。其實這是典型的java處理事件的方法,這么做可以使得回調(diào)更靈活,可以處理涉及更多線程、對象和類的情況。稍后會給出這種模仿事件處理模型的回調(diào)的實現(xiàn)方法。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 苍山县| 兰考县| 丰都县| 塔城市| 北安市| 延长县| 鲁山县| 台中市| 南部县| 新建县| 大洼县| 武鸣县| 偏关县| 满城县| 麻栗坡县| 平度市| 岚皋县| 元朗区| 柳河县| 紫云| 桐梓县| 永康市| 水城县| 汨罗市| 灌南县| 锡林郭勒盟| 蒙城县| 土默特左旗| 淮安市| 天水市| 喜德县| 高平市| 陇川县| 沙田区| 上蔡县| 罗甸县| 台江县| 九龙县| 新津县| 巴彦淖尔市| 宜春市|