java - 线程不会死,其中两个一直重叠
问题描述
我需要一个一次只运行一次的线程,例如,如果它第一次被调用,它将运行,如果它被第二次调用,第一个应该完全停止并被允许死亡,一个新的应该占用这是地方。我进行了一个小测试,以查看每次执行之间实际发生了什么,结果表明线程没有死,而是两个线程同时执行:
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() 和 Future
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 时对其进行初始化?
解决方案
似乎该方法valid
可以同时调用多次。这意味着,这些调用中的每一个都将等待一个线程(Worker)结束,而它们中的每一个都创建自己的Worker
并且您丢失了指向它的指针,因此无法停止一堆新创建的工作者。您应该使valid
方法同步:synchronized void valid()
它将防止创建许多工作人员:
@Override
synchronized public void valid() {
...
}
还有一件事要说。您将while循环放在try-catch之外,这是错误的:如果tread被中断,中断不会杀死它,因为下一个interation开始了,所以应该是这样的:
@Override
public void run() {
try {
while (running) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(2000);
}
catch (InterruptedException iex) {
//you don't need here Thread.currentThread().interrupt() call, because the thread has alredy been interrupted.
// The return statement here is also obsolete, I just use it as an example, but you can use empty braces.
return;
}
}
}
推荐阅读
- .net - 如何使用 dotnet 命令创建 nuget 元包?
- android - Firebase Crashlytics 报告 InflateException: ResourceNotFoundException for a Trend TaintArt for 4x6
- scala - IntelliJ 显示有关依赖方法类型的类型不匹配错误,即使 sbt 编译良好(scala)
- node.js - 缺少到 POST 的路线
- python - 使用 model_main.py 进行训练对象检测失败并出现 Windows 致命异常:访问冲突
- c++ - 如何获取呼叫行号和文件名
- python - 如何对字典中的值是python中的列表进行排序
- c# - 从 IHttpContextAccessor 获取 RouteValues
- c++ - 陷入无限循环
- amazon-dynamodb - DynamoDB:多次调用具有相同 ClientRequestToken 的 TransactWriteItems 以实现幂等性