0

これらのような同様の質問を探していましたが、私の要件には特別なものが必要だと思います。詳しく説明します。

まず、以前はこのように機能していたシステムを移行する必要があります。

  1. ServerPool(Thread) というクラスは、メイン クラスで初期化されます。
  2. この ServerPool は、ソケットを受信するためのキューと、ワーカー スレッドを管理するためのベクトルを作成します (S.

したがって、プールのコードには次のものがあります。

public class ServerPool extends Thread {
    private LinkedBlockingQueue<SearchQuery> workQueue; //SearchQuery is a Class I defined which can handle two type of processes (for sockets and for single Strings)
    private Vector<SearchThread> workers;
    private final int NTHREADS = 10;
    private int typeOfQuery;

    public ServerPool() {
    workers = new Vector<SearchThread>(NUM_THREAD);
    workQueue = new LinkedBlockingQueue<SearchQuery>();
    this.typeOfQuery = typeOfQuery;
    SearchThread search = new SearchThread(workQueue);
    search.start();
    workers.add(search);
}

public void run() {
    while(true){
    SearchQuery client = null;

    if (typeOfQuery == 1) {
        client = new SocketQuery(....);
        } else if (typeOfQuery == 2) {
        client = new StringQuery(...);
        }
        workQueue.put(client);
}
}

プロセスを実行する SearchThread の場合:

public class SearchThread extends Thread {
    private LinkedBlockingQueue<SearchQuery> workQueue = null;
    private SearchQuery request = null;

    public SearchThread(LinkedBlockingQueue<SearchQuery> workSource) {
        workQueue = workSource;
    }   

    public void run() {
        request = workQueue.take();
        //Here I process the request
        //And use a PrintWriter to give a "response"            
    }

}

これは以前はソケットでtelnetを使って動いていたのですが、今はWebサービスに変換してほしいと依頼されたので、Webサービスとしては値を返すはずなので、Callable、Future、Thread Poolsを使うことを考えていますが、まったく同じ動作を再現できないため、これを実装してみました:

public class NewServerPool {

    private final int NTHREADS = 10;
    private ExecutorService executor;
    private LinkedBlockingQueue<SearchQuery> workQueue;
    private Vector<Future<String>> futures;
    private boolean end = true;

    public NewServerPool(int port, SearchQuery typeOfQuery) {
        executor = Executors.newFixedThreadPool(NTHREADS);
        workQueue = new LinkedBlockingQueue<SearchQuery>();
        futures = new Vector<Future<String>>();

    }


}

そして、今では Callable になっている検索スレッドの場合

public class NewSearchThread implements Callable<String>{

    private SearchQuery searchQuery;

    public NewSearchThread(SearchQuery searchQuery) {
        this.searchQuery = searchQuery;
    }

    @Override
    public String call() throws Exception {
        String xmlResponse = null;

        if (searchQuery == null) {
            throw new InvalidSearchQueryException("The search query is not valid or has null value: " + searchQuery);
        }

        if (searchQuery instanceof SocketTimed) {
            System.out.println("It is socket timed query type");
        } else if (searchQuery instanceof WebServiceQuery) {
            System.out.println("It is a web service query type");
        }

        xmlResponse = searchQuery.manageResponse();

        return xmlResponse;
    }

この場合、WebService がサーバー プール (NewServerPool) の新しいインスタンスを呼び出すと仮定すると、サーバー プールでスタックしてしまいました。どうすればこれを続行できますか? 誰かが私を助けてくれれば、本当に感謝します。よろしくお願いします。

4

2 に答える 2

2

いくつかのこと:

まず、元のServerPoolクラスに欠陥があり、 のインスタンスを 1 つだけインスタンス化しますSearchThreadNTHREADS(10)秒を開始するつもりだったと思いますSearchThread

NewSearchThread次に、のアプローチを少し変更したように見えますSearchThread- のコンストラクターは引数をNewSearchThread取りますが、. SearchQuerySearchThreadSearchQueryBlockingQueue

最後に、あなたのクラスNewServerPoolは とはアプローチが異なります。その方法はServerPool、新しい を に継続的に配置します。対照的に、のコンストラクターはシングルを取り、それに対して何もしません。 ServerPoolrun()SearchQueryBlockingQueueNewServerPoolSearchQuery

始めるには、次のようなものはいかがですか。

public class NewServerPool extends Thread {

    private final int NTHREADS = 10;
    private ExecutorService executor;
    private Vector<Future<String>> futures;

    public NewServerPool(int port, SearchQuery typeOfQuery) {
        executor = Executors.newFixedThreadPool(NTHREADS);
        futures = new Vector<Future<String>>();
    }

    public void run() {
        while(true){
            SearchQuery client = null;

            if (typeOfQuery == 1) {
                client = new SocketQuery(....);
            } else if (typeOfQuery == 2) {
                client = new StringQuery(...);
            }
            futures.add(executor.submit(new NewSearchThread(client)));
        }
    }
}

「始めに」と言っていることに注意してください...上記には、run()リクエストの処理を停止するときにメソッドを適切に終了するなどの追加が必要なためです(ただし、それは別のトピックです)。

于 2013-05-10T22:16:30.580 に答える
2

NewServerThreadPoolスレッドプールを「起動」して値を返したいだけの場合、拡張する理由はないように思えますThread(ただし、達成しようとしていることの完全な仕様を知らなくても、私は100%ではありません承知しました)。起動メソッドが返す値のタイプは何ですか? boolean? String? int? 代わりに、次のようなことを試すことができます。

public class NewServerPool {

    private final int NTHREADS = 10;
    private ExecutorService executor;
    private Vector<Future<String>> futures;

    public NewServerPool(int port, SearchQuery typeOfQuery) {
        futures = new Vector<Future<String>>();
    }

    public boolean launchThreadPool() {
        executor = Executors.newFixedThreadPool(NTHREADS);
        return true;
    }

    public void submitToThreadPoolForProcessing(SearchQuery client) {
        futures.add(executor.submit(new NewSearchThread(client)));
    }

    public Vector<Future<String>> getFutures() {
        return futures;
    }
}

上記では、launchThreadPool()メソッドの単一行のコンテンツは (以前の投稿のように) 簡単にコンストラクターの一部にすることができますが、それを独自のメソッドに分割すると、起動後に "値を返すことができます"ことに注意してください。示されているように、boolean値が返されます (常に true が返されます) が、もちろん、仕様が要求する型を返すようにメソッドを変更できます。

于 2013-05-14T15:25:31.153 に答える