2016-08-13 90 views
0

我正在製作一個類似Skype的程序。我有一個「接受」線程和每個調用的多個用戶線程。每次開始通話時,我都會將接受線程存儲在數組列表中。我需要做的是當調用中少於兩個人中斷接受發送該命令的用戶線程的接受線程時。爲了在創建接受線程時做到這一點,我記錄索引號並將其傳遞給所有用戶線程,因此當它需要發送中斷命令時,它只需使用索引號從數組列表中獲取線程。但是,當我發送它沒有任何反應。有人能告訴我這是爲什麼嗎?先謝謝你!!!爲什麼我的線程在我中斷時沒有結束?

接收線程

import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.ArrayList; 

public class accept extends Thread { // Chat and Voice Server User Accept 
    private ServerSocket TextChat; 
    private Socket sText; 
    private int TextPort; 
    private int index; 
    boolean running = true; 

    accept(int ChatPort) { 
     TextPort = ChatPort; 
     chat.threads.add(this); 
     index = chat.threads.indexOf(Thread.currentThread()); 
     try { 
      TextChat = new ServerSocket(ChatPort); 
     } catch (IOException e) { 
      System.out.println("Cant create server on port "+ ChatPort); 
      try { 
       TextChat.close(); 
      } catch (IOException e1) { 
       e1.printStackTrace(); 
      } 
     } 
    } 
    public void run() { 
     while(running == true) { 
      try { 
       sText = TextChat.accept(); 
       System.out.println(sText+" Joined the chat"); 
       new TextChat(sText, TextPort, index).start(); 
      } catch (IOException e) { 
       System.out.println("Server on port "+TextChat+" Can't Accept"); 
       try { 
        TextChat.close(); 
       } catch (IOException e1) { 
        e1.printStackTrace(); 
       } 
      } 
     } 
     System.out.println("Server on port "+TextChat+" Is Shutting Down"); 
     try { 
      TextChat.close(); 
     } catch (IOException e1) { 
      e1.printStackTrace(); 
     } 
    } 
    public void setRunning(boolean run) { 
     running = run; 
    } 
} 

用戶線程

import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.Socket; 
import java.util.ArrayList; 

public class TextChat extends Thread { 
    private ObjectOutputStream out; 
    private ObjectInputStream in; 
    private Socket s; 
    private String msg; 
    private Boolean running = true; 
    private int port; 
    private String name; 
private int threadIndex; 

TextChat(Socket sText, int TextPort, int index) { 
    s = sText; 
    port = TextPort; 
    threadIndex = index; 
    try { 
     out = new ObjectOutputStream(s.getOutputStream()); 
     if(port <= 65511) { 
      chat.users1.add(out); 
     }else { 
      chat.users2.add(out); 
     } 
     in = new ObjectInputStream(s.getInputStream()); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 
public void run() { 
    while(running == true) { 
     try { 
      msg = in.readObject().toString(); 
      String[] part = msg.split("/"); 
       if(part[0].equals("MYNAME")) { 
        name = part[1]; 
        System.out.println("NAME ADDED "+name); 
       } 
       if(!msg.equals(null)) { 
        if(port <= 65511) { 
         for(ObjectOutputStream o : chat.users1) { 
          o.writeObject(name+": "+msg); 
         } 
        }else { 
         for(ObjectOutputStream o : chat.users2) { 
          o.writeObject(name+": "+msg); 
         } 
        } 
       } 
      } catch (ClassNotFoundException | IOException e) { 
       System.out.println(name+" Disconneted from chat"); 
       if(port <= 65511) { 
        chat.users1.remove(out); 
       }else { 
        chat.users2.remove(out); 
       } 
       if(chat.users1.size() < 2) { 
        System.out.println("Chat server on port "+port+" is shutting down due to not enough people in call"); 
        chat.threads.get(threadIndex).running = false; 
        running = false; 
       } 
      } 
     } 
    } 
} 
+0

如果您很快就沒有得到正確的答案,可以考慮通過創建一個小程序(最小的程序,我們可以編譯和運行不變),然後測試和修改,以及向我們顯示問題,[mcve]。 –

+0

我已經做了。我的問題是,我不能訪問接受線程中的任何對象,我不能打斷它。幾個小時後,我一直在與它纏身。 – mardis7021

+0

不,你沒有。請仔細檢查您發佈的內容,因爲我們既不能編譯也不能運行它 –

回答

2

當你中斷一個線程,它所做的就是設置一個標誌。這個標誌被一些操作監視,但除非你正在使用這些操作之一,否則什麼都不會發生。

如果你有一個在IO上被阻塞的線程,最有效的爲什麼解鎖線程是關閉()流或套接字來殺死它。我還會設置一個標誌,例如boolean closed,因此您可以檢測到拋出的任何IOException是關閉套接字的原因,而不是錯誤。

編輯:一些建議。

  • 總是使用TitleCase作爲類名。
  • 儘可能避免可變字段static字段。在這種情況下,我不相信你需要任何。
  • 總是通過共享狀態,並確保它是線程安全的,從多個線程中使用。
  • 不要延長Thread而實現Runnable,並用它包裝到一個Thread
  • 你只需要一個服務器端口在此情況下,除非你實現這是一個對等網絡服務,但不似乎是這種情況。
  • while (running)需要時,無需編寫像while (running == true)這樣的詳細表達式。
  • 如果您有線程間共享的boolean running請確保它是易失性的。
  • 不要發現異常並假裝它沒有發生。你最好在構造函數throws IOException而不是創建一個死對象。
  • 將每個客戶端包裝在一個對象中,只註冊該對象,而不是運行該對象的線程。正如你所指出的,保持線程不是很有用。
  • 當您不期望null的值時,請勿使用像Boolean這樣的包裝。使用boolean而不是null
  • 我建議使用默認爲false的標誌。而不是running使用closed。這使得更容易知道變量的默認值/正常值是什麼。
  • 不要在代碼中硬編碼這樣的端口,你應該通過一個標誌或一個id來說明它應該如何表現。
  • 只能使用對象流來傳遞一般對象。爲了傳遞文本,您可以使用更簡單的Writer/Reader或Data Stream。
  • 您不需要檢查null的值,該值不能爲nullmsg.equals(null)不能每回true
  • 在您的IDE中使用拼寫檢查程序Disconneted應該是Disconnected
  • 當有人可能要加入時,我不會斷開連接。
+0

我無法訪問線程中的任何對象。 – mardis7021

+0

@ mardis7021您可以訪問該線程中的對象的線程。爲什麼你不能訪問它中的任何對象?這是家庭作業的要求,還是你不知道怎麼做? –

+0

@ mardis7021 BTW這個代碼的結構有很多我會改變。 –

相關問題