Java создает фоновый поток, который периодически что-то делает
Можно ли создать отдельный фоновый поток, который бы отдельно что-то делал? Я пробовал следующую программу, но она не работает, как я ожидаю.
public class Test {
private static class UpdaterThread extends Thread {
private final int TIMEOUT = 3000;
public void run() {
while (true) {
try {
Thread.sleep(TIMEOUT);
System.out.println("3 seconds passed");
} catch (InterruptedException ex) {
}
}
}
}
/**
* @param args
* the command line arguments
*/
public static void main(String[] args) {
try {
Thread u = new UpdaterThread();
u.start();
while (true) {
System.out.println("--");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Я ожидал, что каждые 3 секунды "3 секунды прошло" будет напечатано в виде нескольких строк "-". На самом деле "3 секунды прошло" никогда не печатается. Зачем? И как я могу создать фоновый поток, который будет делать что-то независимо от основного потока?
5 ответов
Использование java.util.TimerTask
а также java.util.Timer
:
Timer t = new Timer();
t.scheduleAtFixedRate(
new TimerTask()
{
public void run()
{
System.out.println("3 seconds passed");
}
},
0, // run first occurrence immediately
3000); // run every three seconds
Он печатает "3 секунды прошло". Удалить System.out.println("--")
и вы их увидите легче;-)
Теперь вы также можете использовать ScheduledExecutorService
и использовать Runnable
вместо Thread
:
public class Test {
private static class Updater implements Runnable {
@Override
public void run() {
System.out.println("3 seconds passed");
}
}
public static void main(String[] args) throws InterruptedException {
Runnable r = new Updater();
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
service.scheduleAtFixedRate(r, 0, 3, TimeUnit.SECONDS);
Thread.sleep(10000);
service.shutdown();
}
}
Вы можете использовать вышеупомянутый подход для периодического запуска, хотя TimerTask
может быть проще.
Что касается вашего вывода, я подозреваю, что ваш основной поток не позволяет вашему UpdaterThread
бежать, так как это в очень узкой петле. Обратите внимание, что это будет зависеть от доступных процессоров / ядер и т. Д.
Рассматривали ли вы спать в своем основном потоке или с помощью Thread.yield ()? Обратите внимание на условия на этой связанной странице:
Когда использовать yield()?
Я бы сказал, практически никогда. Его поведение стандартно не определено, и, как правило, есть более эффективные способы выполнения задач, которые вы, возможно, захотите выполнить с помощью yield(): если вы пытаетесь использовать только часть ЦП, вы можете сделать это более управляемым способ, оценивая, сколько ЦП потратил поток в последнем фрагменте обработки, а затем спит некоторое время для компенсации: см. метод sleep();
Обратите внимание также на эту интересную статью по обработке прерываний потоков.
Есть много ответов, но никто не говорит, почему его пример не работал. System.out
является выходным потоком, поэтому после того, как вы начали запись в этот поток, JAVA блокирует его, и все остальные потоки будут ждать, пока блокировка будет применена к потоку. После того, как поток будет разблокирован, другой поток сможет работать с этим потоком.
Чтобы ваш пример работал, вы должны добавить Thread.sleep
в while
петля в основном потоке.
Я бы порекомендовал использовать ScheduledExecutorService
, Запустить свой UpdaterThread()
каждые 3 секунды вы можете сделать так:
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new UpdaterThread(), 0, 3000, TimeUnit.MILLISECONDS);
Вы можете прочитать больше здесь: Java Tutorials - Executor Interfaces.