web-dev-qa-db-ja.com

NetBeans / Java /新しいヒント:Thread.sleepがループで呼び出される

NetBeansには、次の新しいヒントがあります:Thread.sleep called in loop。

質問1:ループでスリープすることはどのように/いつ問題になりますか?

質問2:問題がある場合は、代わりに何をすればよいですか?

更新:質問3:ここにいくつかのコードがあります。この場合、ループでThread.Sleepの代わりに他の何かを使用する必要があるかどうかを教えてください。要するに、これは、クライアントTCP接続をリッスンするサーバーによって使用されます。クライアントとのセッションの最大数に達した場合、ここでスリープが使用されます。この状況では、アプリケーションが必要です無料のセッションが利用可能になるまで待機します。

public class SessionManager {
    private static final int DEFAULT_PORT = 7500;
    private static final int SLEEP_TIME = 200;
    private final DatabaseManager database = new DatabaseManager();
    private final ServerSocket serverSocket = new ServerSocket(DEFAULT_PORT);

public SessionManager() throws IOException, SQLException
{
}

public void listen()
{
while (true)
    if (Session.getSessionCount() < Session.getMaxSessionCount())
        try
        {
             new Thread(new Session(database, serverSocket.accept())).start();
        }
        catch (IOException ex) { ex.printStackTrace(); }
    else
        try
        {
            Thread.sleep(SLEEP_TIME);
        }
        catch (InterruptedException ex) { ex.printStackTrace(); }
}

public static void main(String[] args) throws IOException, SQLException
{
new SessionManager().listen();
}
}
47
asmo

通常、ループでスリープを呼び出すと、パフォーマンスが低下します。例えば:

while (true) {
    if (stream.available() > 0) {
       // read input
    }
    sleep(MILLISECONDS);
}

MILLISECONDSが大きすぎる場合、このコードは入力が利用可能であることを認識するまでに時間がかかります。

MILLISECONDSが小さすぎる場合、このコードは、まだ到着していない入力の多くのシステムリソースチェックを無駄にします。

ループ内でのsleepのその他の使用も、通常は疑わしいものです。通常、より良い方法があります。

それが問題である場合、代わりに何をすべきですか?

コードを投稿すると、多分私たちはあなたに賢明な答えを与えることができます。

[〜#〜] edit [〜#〜]

IMO、問題を解決するより良い方法は ThreadPoolExecutor を使用することです。

このようなもの:

public void listen() {
    BlockingQueue queue = new SynchronousQueue();
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
            1, Session.getMaxSessionCount(), 100, TimeUnit.SECONDS, queue);
    while (true) {
        try {
            queue.submit(new Session(database, serverSocket.accept()));
        } catch (IOException ex) { 
            ex.printStackTrace();
        }
    }
}

これにより、現在のコードの動作に合わせてエグゼキューターが構成されます。他にもいくつかの方法があります。上記のjavadocリンクを参照してください。

22
Stephen C

ループ内でsleep()メソッドの完全に合法的な使用に出くわすと思います。

サーバーとクライアントの間には一方向の接続があります。したがって、クライアントがサーバーとの非同期通信を実現する場合、サーバーにメッセージを送信し、サーバーからの応答を定期的にポーリングします。タイムアウト間隔が必要です。

Response resp = null;
for (int i = 0; i < POLL_REPEAT && resp == null; i++) {
    try {
       Thread.sleep(POLL_INTERVAL);
    } catch (InterruptedException ie) {
    }
    resp = server.getResponse(workflowId);
}

POLL_REPEAT * POLL_INTERVAL〜タイムアウト間隔

3
Ondrej Bozek

他の人が言ったように、それは使用法に依存します。合法的な使用とは、10秒ごとに何かを行うように設計されたプログラムです(ただし、厳密なタイミングが必要なほど重要ではありません)。データやその他のタスクを数分ごとにインポートするこれらの「ユーティリティアプリ」がたくさんあります。これは、これらのタスクを実行する簡単な方法です。通常、スリープ間隔を非常に低く設定し、プログラムを応答性に保ち、簡単に終了できるようにカウンターを使用します。

int count = 0;
while (true) {

    try {
        // Wait for 1 second.
        Thread.sleep(1000);
    }
    catch (InterruptedException ex) {}

    // Check to see if the program should exit due to other conditions.
    if (shouldExit())
        break;

    // Is 10 seconds up yet? If not, just loop back around.
    count++;
    if (count < 10) continue;

    // 10 seconds is up. Reset the counter and do something important.
    count = 0;
    this.doSomething();
}
3
java nut

どのように/いつループで寝ることが問題になるのでしょうか?
適切な同期方法(待機/通知など)の代わりに使用する場合があります。

それが問題である場合、代わりに何をすべきですか?
あなたが何をしているかによって異なります。これを行うことが最善のアプローチである状況を想像するのは難しいですが、それも可能性があると思います。

この件について Sunの並行性チュートリアル を確認できます。

2
Nikita Rybak

これは最善の解決策ではありませんが、Thread.sleep(1);のようにミリ秒数を小さくすることができます

0
Cergo