大家知道, 在我們寫多線程的時候, 往往要Extends Thread來實現一個線程, 通過覆蓋Run()來改寫start()方法, 在很多情況下, 我們還有可能用implements Runnable來實現一個線程,他們有什麼區別?
讓我們來看一個例子:假設我們需要實現一個對象, 每個一段時間來檢測一個服務器的端口是否還在活動,我們編寫一個對象, 如下代碼:
package com.collegesoft;
import java.net.URL;
import java.net.HttpURLConnection;
import java.io.*;
import java.net.*;
public class SendMsg extends Thread {
public final static int SYSISOK=1;
public final static int SYSISDOWN=-1;
public final static int SYSISOUTOFTIME=0;
public final static int SYSISEXCEPTION=-3;
String testURL;
private URL url;
boolean needStop=false;
/**
* 讀取是否需要停止主線程
* @return 停止標誌符
*/
public synchronized boolean getNeedStop(){
return needStop;
}
/**
* 設置是否需要停止主線程 , 如果在外部調用 改線程的start()方法, 可以使用setNeedStop(true)來停止
* @param b 停止標誌符
*/
public synchronized void setNeedStop(boolean b){
needStop=b;
}
/**
* 構造器
* @param testURL 要檢測的URL
*/
public SendMsg(String testURL){
this.testURL =testURL;
}
/**
* 被檢測系統的狀態
*/
private int sysState=0;
/**
* 設置被檢測系統的狀態, 也可用於清零復位處理
* @param state 即將設置的狀態。
*/
public synchronized void setSysState(int state){
System.out.println("set state ="+state);
this.sysState =state;
}
/**
* 返回被檢測系統的當前狀態
* @return 被檢測系統的當前狀態 0:無響應, 1:正常, -1:當機 ,-3 :其他錯誤
*/
public synchronized int getSysState(){
return sysState;
}
public void run(){
while (!needStop ){
new TestURLThread(this).start() ;
synchronized (this){
try{
this.wait(30*1000);
}catch(InterruptedException e) {
}
if (getSysState() == SYSISOK ) {
System.out.println("一切正常");
}
else if (getSysState() == SYSISDOWN ) {
System.out.println("系統蕩機");
}
else if(getSysState()==SYSISOUTOFTIME ){
System.out.println("系統長時間無響應");
}else{
System.out.println("系統發生其他錯誤");
}
}
}
}
public static void main(String[] args) {
new SendMsg("http://www.163.com").start();
}
/*************************************************************************
* 內部類開始
************************************************************************/
class TestURLThread extends Thread{
SendMsg sendSmg=null;
TestURLThread(SendMsg send ){
sendSmg =send;
}
/**
* 作爲Thread繼承類 , 覆蓋父類run方法
*/
public void run(){
//先復位
setSysState(sendSmg.SYSISOUTOFTIME);
HttpURLConnection httpCon = null;
String results ;
try {
url = new URL(testURL);
httpCon = (HttpURLConnection) url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
results = in.readLine();
httpCon.disconnect();
setSysState(sendSmg.SYSISOK );
/**
* 如果你不希望立即通知 sendSmg線程, 一下同步體可以去除!
*/
synchronized (sendSmg){
sendSmg.notify();
System.out.println("notify sendSMG");
}
}
catch (ConnectException ex) {
//如果建立連接異常,表示系統已斷
setSysState(sendSmg.SYSISDOWN );
/**
* 如果你不希望立即通知 sendSmg線程, 一下同步體可以去除!
*/
synchronized (sendSmg){
sendSmg.notify();
}
}
catch (Exception ex) {
setSysState(sendSmg.SYSISEXCEPTION);
/**
* 如果你不希望立即通知 sendSmg線程, 一下同步體可以去除!
*/
synchronized (sendSmg){
sendSmg.notify();
}
}
finally {
if (httpCon != null) {
httpCon.disconnect();
httpCon = null;
}
}
}
}
/*************************************************************************
* 內部類結束
************************************************************************/
}
我們在這個例子中, 用TestURLThread來測試163網站的80端口, 一旦有結果就notify() SendMsg線程的wait()方法, 不至於讓他傻傻的等,現在的問題是, 我們是否可以將 TestURLThread不重Thread繼承, 而是擴展Runnable接口來實現, 在SendMsg中用
new TestURLThread(this).run() ;來調用TestURLThread的run()方法?
答案是否定的
因爲, 一旦替換成Runnable之後, 在TestURLThread的run裏面, sendMSsg.notify()將不能及時喚醒SendMsg的wait(),只能靠 this.wait(30*1000);來退出等待。
這是我發現現象後得出的結論, 希望網友討論, 是否有道理, 或者理由是什麼