it-swarm.com.ru

NetBeans/Java/Новая подсказка: Thread.sleep вызывается в цикле

В NetBeans есть новый совет, который говорит: Thread.sleep вызывается в цикле.

Вопрос 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();
}
}
46
asmo

Вызов сна в цикле обычно приводит к снижению производительности. Например:

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

Если MILLISECONDS слишком велик, то этот код займет много времени, чтобы понять, что входные данные доступны.

Если MILLISECONDS слишком мал, то этот код будет тратить много ресурсов на проверку системных ресурсов для ввода, который еще не поступил.

Другие варианты использования sleep в цикле также сомнительны. Там обычно лучший способ.

Если это проблема, что мне делать вместо этого?

Разместите код, и, возможно, мы сможем дать вам разумный ответ.

ПРАВКА

ИМО, лучший способ решить эту проблему - использовать 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

Как уже говорили другие, это зависит от использования. Законное использование - это программа, предназначенная для выполнения каких-либо действий каждые 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

Я думаю, что натолкнулся на одно вполне законное использование метода 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 ~ интервал TIMEOUT

2
Ondrej Bozek

Как/когда может быть проблемой спать в цикле?
Люди иногда используют его вместо правильных методов синхронизации (таких как ожидание/уведомление).

Если это проблема, что мне делать вместо этого?
Зависит от того, что вы делаете. Хотя мне сложно представить ситуацию, когда это лучший подход, я думаю, это тоже возможно.

Вы можете проверить учебник Sun по параллелизму на эту тему.

2
Nikita Rybak

Это не лучшее решение, но вы можете уменьшить количество миллисекунд, например Thread.sleep(1);

0
Cergo