【发布时间】:2020-02-03 11:31:49
【问题描述】:
我需要一个一次只运行一次的线程,例如,如果它第一次被调用,它将运行,如果它被第二次调用,第一次应该完全停止并被允许死掉,然后一个新的应该取而代之。 我进行了一个小测试,看看每次执行之间实际发生了什么,结果表明线程没有死,而是两个线程同时执行:
public class Test {
Worker worker = new Worker();
@Override
public void valid() {
try {
if (worker.running) {
worker.running = false;
worker.join();
}
} catch (InterruptedException iex) {
worker.running = false;
}
worker = new Worker();
worker.start();
}
private final class Worker extends Thread {
private volatile boolean running = true;
@Override
public void run() {
while (running) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException iex) {
Thread.currentThread().interrupt();
}
}
}
}
}
结果如下:
//Upon first execution
Thread-4
Thread-4
Thread-4
Thread-4
//When I execute it again
Thread-7
Thread-4
Thread-7
Thread-4
Thread-7
Thread-4
我尝试使用ExecutorService 或while(!Thread.currentThread.isInterrupted) 代替布尔标志,并得到相同的结果。
如何正确停止“Thread-4”并只运行其中一个?
实际问题来自一个线程,该线程将循环遍历列表并根据请求更新不和谐聊天中的内容,线程所做的是根据肾脏的建议收听输入和更改我正在尝试使用 executor.submit()和未来
private ExecutorService executor = Executors.newSingleThreadExecutor();
private Future<Void> worker;
private void setupImageThread() {
if (!worker.isDone() && !worker.isCancelled()) {
worker.cancel(true);
}
this.worker = (Future<Void>)executor.submit(new Cycler(Listener.queue(), this.links, Cel.cMember()));
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
Runnable timeout = () -> {
executor.shutdown();
};
ses.schedule(timeout, 100, TimeUnit.SECONDS);
}
如何在 Future 第一次创建时对其进行初始化?
【问题讨论】:
-
Test 对象是如何创建的? Test.valid 是怎么调用的?
-
它由来自EventListener的用户输入调用,当它被调用时它只运行一次valid(),该类实际上实现了一个带有该方法的功能接口。如果重要的话,这来自 Discord JDA 项目。
-
我们保证我们创建一个测试实例?然后在同一个实例上多次调用 valid() ? (我对这个问题没有理论,我只是想掌握全局)
-
它的创建方式是对类的引用以 TEST(Test::new) 的形式存储在 Enum 常量中,每次调用它都会使用 @ 调用指定类中的有效方法987654327@ 所以我猜每次都是一个新实例?我对多线程还很陌生,所以我不确定。
-
我建议使用single thread executor,它可以保证任务的顺序处理。
标签: java multithreading