1

datagramPacket を送受信できるクラス SipProvider を作成しています。このクラスは、私が取り組んでいる SIP スタックの一部です。

私が提供した API では、SipProvider が実行可能または拡張スレッドを実装することはありません。

私が実装しようとしている解決策は、スレッドを拡張する 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();
        }
    }
}
}

エディス:

提案されたもの(完全に機能する)以外に私が見つけたもう1つの解決策は、新しいスレッドをインスタンス化し、同時にそのrun()メソッドを定義することです。この例のメソッド startOn は、listeningPoint (使用されているポート アドレスとプロトコルに関する情報を含む) でリッスンを開始します。

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;
} 
4

1 に答える 1

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.

于 2013-01-11T13:20:03.740 に答える