Java平台從開始就被設計成為多線程環境
在你的主程序執行的時候
其它作業如碎片收集和事件處理則是在後台進行的
本質上
你可以認為這些作業是線程
它們正好是系統管理線程
但是無論如何
它們是線程
線程使你能夠定義相互獨立的作業
彼此之間互不干擾
系統將交換這些作業進或出CPU
這樣(從外部看來)它們好象是同時運行的
在你需要在你的程序中處理多個作業時
你也可以使用多個進程
這些進程可以是你自己創建的
你也可以操縱系統線程
你進行這些多作業處理
要使用幾個不同的類或接口
java
util
Timer類
javax
swing
Timer類
Thread類
Runnable接口
對於簡單的作業
通常需要重復的
你可以使用java
util
Timer類告訴它
每半秒鐘做一次
注意
大多數系統例程是使用毫秒的
半秒鐘是
毫秒
你希望Timer實現的任務是在java
util
TimerTask實例中定義的
其中運行的方法包含要執行的任務
這些在Hi類中進行了演示
其中字符串
Hi
重復地被顯示在屏幕上
直到你按Enter鍵
import java
util
*;
public class Hi
{
public static void main
(String args[])
throws java
io
IOException
{
TimerTask task = new TimerTask()
{
public void run()
{
System
out
println(
Hi
);
}
};
Timer timer = new Timer();
timer
schedule(task
);
System
out
println
(
Press ENTER to stop
);
System
in
read(new byte[
]);
timer
cancel();
}
}
Java Runtime Environment工作的方式是只要有一個線程在運行
程序就不退出
這樣
當取消被調用
沒有其它線程在運行了
則程序退出
有一些系統線程在運行
如碎片收集程序
這些系統線程也被稱為後台線程
後台線程的存在不影響運行環境被關閉
只有非後台線程保證運行環境不被關閉
Javax
swing
Timer類與java
util
timer類的工作方式相似
但是有一些差別需要注意
第一
運行的作業被ActionListener接口的實現來定義
第二
作業的執行是在事件處理線程內部進行的
而不象java
util
Timer類是在它的外部
這是很重要的
因為它關系到Swing組件集是如何設計的
如果你不熟悉Swing
它是一組可以被Java程序使用的圖形組件
Swing被設計程被稱為單線程的
這意味著對Swing類內部內容的訪問必須在單個線程中完成
這個特定的線程是事件處理線程
這樣
例如你想改變Label組件的文字
你不能僅僅調用Jlabel的setText方法
相反
你必須確認setText調用發生在事件處理線程中
而這正是javax
swing
Time類派的上用場的地方
為了說明這第二種情況
下面的程序顯示一個增加的計數器的值
美半秒鐘計數器的數值增加
並且新的數值被顯示:
import javax
swing
*;
import java
awt
*;
import java
awt
event
*;
public class Count
{
public static void
main(String args[])
{
JFrame frame = new JFrame();
frame
setDefaultCloseOperation
(JFrame
EXIT_ON_CLOSE);
Container contentPane =
frame
getContentPane();
final JLabel label =
new JLabel(
JLabel
CENTER);
label
setFont(new Font
(
Serif
Font
PLAIN
));
contentPane
add(label
BorderLayout
CENTER);
ActionListener listener
= new ActionListener()
{
int count =
;
public void actionPerformed
(ActionEvent e)
{
count++;
label
setText
(Integer
toString(count));
}
};
Timer timer = new Timer(
listener);
timer
start();
frame
setSize(
);
frame
show();
}
}
上述程序的結果是
萬一你要做的不是一個簡單的重復作業
java
lang
Thread類就派上了用場
它允許你自己控制基本功能
通過創建Thread的一個子類
你可以使你的系統脫離
並進行一個長時間運行的作業
如從網絡上讀取一個文件
而不阻礙你的其它程序的運行
這種長時間運行的作業將在run方法中定義
第二種方式是創建Thread類的子類並在子類中實現run方法
或在實現runnable的類中實現run方法
並將這個實現傳遞給Thread的構造函數
你可能會問有什麼區別
Java編程語言僅支持單一繼承
如果你設計的調用是除了Thread以外的其它類
你可以是你的類實現Runnable
而它可以是你的作業被執行
否則
你定義Thread的子類來運行你的Run方法
在處理過程中不再添加其它操作
對於創建Thread子類的第三種情況
下面的程序生成了一個新的線程來計算一個特定URL的字符數
這個URL是通過命令行傳遞進來的
在這進行過程之中
實現Runnable的第四種情況被演示
打印出重復的消息
注意在實現Runnable的這後一種情況下
你必須提供重復消息的代碼
你必須同時sleep
以分配時間並完成操作
在兩種情況下
與使用Timer相比較
這段程序的最後一部分包含有你從命令行讀取命令以觸發程序結束
注意在系統讀取URL並打印消息的同時
你總可以按Enter鍵結束程序
import java
io
*;
import
*;
public class Both
{
public static void
main(String args[])
{
final String urlString = args[
];
final String message = args[
];
Thread thread
= new Thread()
{
public void run()
{
try
{
URL url = new URL(urlString);
URLConnection connection =
url
openConnection();
InputStreamReader isr = new
InputStreamReader(
connection
getInputStream());
BufferedReader reader =
new BufferedReader(isr);
int count =
;
while (reader
read() !=
)
{
count++;
}
System
out
println(
Size is :
+ count);
reader
close();
} catch (MalformedURLException e)
{
System
err
println(
Bad URL:
+ urlString);
} catch (IOException e)
{
System
err
println
(
I/O Problems
);
}
}
};
thread
start();
Runnable runnable = new Runnable()
{
public void run()
{
while(true)
{
System
out
println(message);
try
{
Thread
sleep(
);
} catch (InterruptedException e)
{
}
}
}
};
Thread thread
= new Thread(runnable);
thread
start();
try {
System
out
println
(
Press ENTER to stop
);
System
in
read(new byte[
]);
} catch (IOException e)
{
System
out
println(
I/O problems
);
}
System
exit(
);
}
}
因為有多種方式來處理線程
你選用哪種技術取決於你和你面臨的條件
要成為一個有效的Java編程人員
盡管你通常不必學習Java編程語言的所有內容和核心庫
但是線程是一個例外
你越早了解線程如何工作和如何使用線程
你將越早了解Java程序如何工作和交互
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27654.html