2013-01-11 58 views
1

我正在編寫一個可以接收和發送datagramPacket的類SipProvider。這個類是我正在開發的SIP堆棧的一部分。使用Java類中的線程而不實現Runnable也不擴展線程

我提供的API不會使SipProvider實現Runnable或擴展線程。

我試圖實現的解決方案是在SipProvider中創建一個新類,它將擴展線程。我想給線程的參數,我有一個編譯問題(沒有可以訪問類型SipProvider的封閉實例),線程無法實例化,因爲它與SipProvider有關(我發現它應該是靜態的,但不知道怎麼做)。

我查了互聯網上如何實現一個類內的線程,但沒有找到解決方案。有沒有一種已知的方式來做到這一點。

這是我一直在試圖做的一個快照。這只是班上的一部分。

public class SipProvider { 

    //startOn is the method which allow the user to listen on a port 
    //so the user don't have to bother creating a thread and so on 
public static SipProvider startOn(listeningPoint) { 
     SipProvider sipProvider = new SipProvider(); 
     thread.sipProvider = sipProvider; 
     thread.run(); 
     return sipProvider; 
} 

    //this is the thread i want to handle the listening process 
public class ReceiveThread extends Thread{ 

    public SipProvider sipProvider; 

    public ReceiveThread(SipProvider sipProvider){ 
     this.sipProvider = sipProvider; 
    } 

    @Override 
    public void run(){ 
     try { 

      int MAX_LEN = 200; 
      DatagramSocket datagramSocket = new DatagramSocket(
        listeningPoint.getPort()); 
      sipProvider.datagramSocket = datagramSocket; 
      byte[] buffer = new byte[MAX_LEN]; 
      DatagramPacket packet = new DatagramPacket(buffer, MAX_LEN); 
      while (!datagramSocket.isClosed()) { 
       sipProvider.setSipListener(sipListener); 
       datagramSocket.receive(packet); 
            //handle packet content 

      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 
} 

EDITH:

另外一個解決方案,我發現除了提出了一個(這完美的作品)是實例化一個新的線程,並在同一時間定義其run()方法。在我的示例中,startOn方法開始偵聽listenPoint(其中包含有關使用的端口地址和協議的信息)。

public static SipProvider startOn(final ListeningPoint listeningPoint) throws SocketException { 
    final SipProvider sipProvider = new SipProvider(listeningPoint); 

    new Thread() { 
     @Override 
     public void run() { 
      try { 

       while (true) { 
DatagramPacket packet = newDatagramPacket(new byte[200], 200); 
sipProvider.datagramSocket.receive(packet); 
String content = new String(packet.getData(), 0, packet.getLength()); 
sipProvider.sipListener.processContent(content); 
       } 

      } catch (Exception e) { 
      } 
     } 
    }.start(); 
    return sipProvider; 
} 
+0

嘗試:新的SipProvider()。新的ReceiveThread() – linski

+0

事情是,我想傳遞對象sipProvider到線程(因爲sipProvider包含有關端口和地址的信息來監聽)。 是否可以編寫: 新的SipProvider()。new ReceiveThread(sipProvider)? – Nourovic

+0

我認爲是的。「新的SipProvider()」部分僅僅是一個滿足編譯器的虛擬實例 - 「沒有可以訪問SipProvider類型的封閉實例」 - 這意味着我需要一個SipProvider實例來實例化ReceiveThread。如果你把你的ReceiveThread放在它自己的文件中,你可以像往常一樣實例化它 – linski

回答

0

這段代碼可以幫助你:

public class SipJob implements Runnable { 

    private SipProvider sipProvider; 

    public SipJob(SipProvider sipProvider) { 
        // pass other parameters, if you need 
     this.sipProvider=sipProvider; 
    } 

    @Override 
    public void run() { 
     // do the code, use SipProvider 

    } 
} 

這將包含要運行的代碼。您可以根據需要將任意數量的參數添加到構造函數中,您可以從業務邏輯中使用它們。我建議不要傳遞資源(例如套接字),因爲它們必須關閉,分離開始和結束代碼是不明智的(同一個實體必須對這兩者負責)。

現在你需要一個Thread執行:

SipProvider sipProvider = ...; 
Runnable job = new SipJob(sipProvider); 
Thread runner = new Thread(job); 
runner.setDaemon(true); 
runner.start(); 

注意 - 據我瞭解 - 這會在後臺運行,所以我設置setDaemon(true)

我不確定,但您可能在SipProvider內有你想要在線程中使用的東西。這樣我建議首先擴展SipProvider類,以便訪問這些內部變量/方法,使用SipJob類中的子類。

編輯:訪問SipProvider的內部的另一種方法是擴展類,並在後代定義SipJob類爲inner class(不是內部靜態類,而是實例類)。這樣,您將自動訪問包含SipProvider的實例變量 - 您甚至不必將其作爲參數傳遞。試試從內部實例類:SipProvider.this.whateverField

相關問題