Runnable VS Thread

    大家知道, 在我們寫多線程的時候, 往往要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);來退出等待。

這是我發現現象後得出的結論, 希望網友討論, 是否有道理, 或者理由是什麼

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章