java - 线程。不在日志中显示“END”
问题描述
我有 2 个类: 第一类我在 LogScheduler 中调用构造函数 - 是单例,构造函数创建新线程并启动它。主线程在 5 秒后进入睡眠状态,然后我将布尔变量设置为 false 以停止循环:
public class Launch {
public static void main(String[] args) throws InterruptedException {
LogScheduler log = LogScheduler.getInstance();
Thread.sleep(5000);
log.setActive(false);
List<String> logs = log.getLogs();
logs.add("ABBA");
log.showLogs();
}
}
二等:
public class LogScheduler {
public static final LogScheduler INSTANCE = new LogScheduler();
private final List<String> logs = new ArrayList<>();
private final Thread worker;
private boolean active = true;
private int i = 0;
private LogScheduler() {
addLog("Launch");
worker = new Thread(this::log);
worker.setName(getClass().getName());
worker.start();
}
private void log() {
addLog("Start");
while (active) {
synchronized (worker) {
try {
System.out.println(Thread.currentThread()
.getName() + " - " + i++);
worker.wait(1000);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
addLog("End");
}
public void addLog(String value) {
logs.add(value);
}
public void showLogs() {
logs.forEach(System.out::println);
}
public List<String> getLogs() {
return logs;
}
public void setActive(boolean active) {
this.active = active;
}
public static LogScheduler getInstance() {
return INSTANCE;
}
public Thread getWorker() {
return worker;
}
}
控制台输出:
job.LogScheduler - 0
job.LogScheduler - 1
job.LogScheduler - 2
job.LogScheduler - 3
job.LogScheduler - 4
Launch
Start
ABBA
'End' - log() 方法中的单词不会显示在控制台中。 请给一些建议来解决它。我尝试同步日志变量和 addLog 方法,它没有帮助。
解决方案
当您设置active
为 false 时,您没有给记录器足够的时间来查看该更改。它正在等待worker.wait
您将 active 设置为 false,然后继续完成程序。
当您设置为活动时,您必须对notify
工人:
public void setActive(boolean active) {
synchronized(worker) {
this.active = active;
worker.notify()
}
}
因此,当您更改活动时,worker.wait
会收到通知。
但是,即使这样,也有会打印最后一个日志的执行,也有不会打印最后一个日志的执行,因为您的程序可能会在工作人员有机会添加最后一个日志之前终止。您需要进一步同步以保证这一点,或者您可以在从 main 返回之前稍等片刻。
你也有数据竞赛。当您添加/读取日志时,您不会同步对共享日志列表的访问。要么同步访问它,要么使用同步的集合来存储日志。
推荐阅读
- python - Python如何获取IP地址的/ 8子网
- php - 连接错误 (2003) 无法连接到 10061 上的 MySQL 服务器
- json - 如何在 jinja 模板文件中将单引号转换为双引号?
- angularjs - AngularJS:在子范围内更改时未调用 $watch
- tensorflow - tensorflow 断言元素 tf.where
- php - 如何在 php codenngiter 的视图页面中获取多个值
- java - 搜索功能的 SQL 查询
- typescript - Webpack worker-loader 无法编译 typescript worker
- square - Square 订单确认电子邮件 - Square API 与 123Formbuilder
- nlp - 使用 nlp 提取年龄相关信息