熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

瘋狂Java講義:加入多線程[1]

2013-11-23 19:59:45  來源: Java高級技術 

   加入多線程

  前面Server和Client只是進行了簡單的通信操作服務器接收到客戶端連接之後服務器向客戶端輸出一個字符串而客戶端也只是讀取服務器的字符串後就退出了實際應用中的客戶端則可能需要和服務器端保持長時間通信即服務器需要不斷地讀取客戶端數據並向客戶端寫入數據客戶端也需要不斷地讀取服務器數據並向服務器寫入數據

  當我們使用傳統BufferedReader的readLine()方法讀取數據時當該方法成功返回之前線程被阻塞程序無法繼續執行考慮到這個原因因此服務器應該為每個Socket單獨啟動一條線程每條線程負責與一個客戶端進行通信

  客戶端讀取服務器數據的線程同樣會被阻塞所以系統應該單獨啟動一條線程該線程專門負責讀取服務器數據

  下面考慮實現一個命令行界面的C/S聊天室應用服務器端則應該包含多條線程每個Socket對應一條線程該線程負責讀取Socket對應輸入流的數據(從客戶端發送過來的數據)並將讀到的數據向每個Socket輸出流發送一遍(將一個客戶端發送的數據廣播給其他客戶端)因此需要在服務器端使用List來保存所有的Socket

  下面是服務器端的實現代碼程序為服務器提供了個類一個是創建ServerSocket監聽的主類一個是負責處理每個Socket通信的線程類

  程序清單codes///MultiThread/server/MyServerjava

  public class MyServer

  {

  //定義保存所有Socket的ArrayList

  public static ArrayList<Socket> socketList = new ArrayList<Socket>()

  public static void main(String[] args)

  throws IOException

  {

  ServerSocket ss = new ServerSocket(

  while(true)

  {

  //此行代碼會阻塞將一直等待別人的連接

  Socket s = ssaccept()

  socketListadd(s)

  //每當客戶端連接後啟動一條ServerThread線程為該客戶端服務

  new Thread(new ServerThread(s))start()

  }

  }

  }

  上面程序是服務器端只負責接受客戶端Socket的連接請求每當客戶端Socket連接到該ServerSocket之後程序將對應Socket加入socketList集合中保存並為該Socket啟動一條線程該線程負責處理該Socket所有的通信任務如程序中四行粗體字代碼所示服務器端線程類的代碼如下

  程序清單codes///MultiThread/server/ServerThreadjava

  //負責處理每個線程通信的線程類

  public class ServerThread implements Runnable

  {

  //定義當前線程所處理的Socket

  Socket s = null;

  //該線程所處理的Socket所對應的輸入流

  BufferedReader br = null;

  public ServerThread(Socket s)

  throws IOException

  {

  thiss = s;

  //初始化該Socket對應的輸入流

  br = new BufferedReader(new InputStreamReader(sgetInputStream()))

  }

  public void run()

  {

  try

  {

  String content = null;

  //采用循環不斷從Socket中讀取客戶端發送過來的數據

  while ((content = readFromClient()) != null)

  {

  //遍歷socketList中的每個Socket

  //將讀到的內容向每個Socket發送一次

  for (Socket s : MyServersocketList)

  {

  PrintStream ps = new PrintStream(sgetOutputStream())

  psprintln(content)

  }

  }

  }

  catch (IOException e)

  {

  //eprintStackTrace()

  }

  }

  //定義讀取客戶端數據的方法

  private String readFromClient()

  {

  try

  {

  return brreadLine()

  }

  //如果捕捉到異常表明該Socket對應的客戶端已經關閉

  catch (IOException e)

  {

  //刪除該Socket

  MyServersocketListremove(s)                                    //①

  }

  return null;

  }

  }

  上面服務器端線程類不斷讀取客戶端數據程序使用readFromClient()方法來讀取客戶端數據如果讀取數據過程中捕獲到IOException異常則表明該Socket對應的客戶端Socket出現了問題(到底什麼問題我們不管反正不正常)程序就將該Socket從socketList中刪除如readFromClient()方法中①號代碼所示

[]  []  


From:http://tw.wingwit.com/Article/program/Java/gj/201311/27783.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.