例如我有一个记日志的类库,其中设计了,一个单例队列,往里塞日志信息。
用另外一个线程去将日志写到硬盘。
那么这里就会存在一定的延迟,假如引用我这个类库的程序被结束了,如何才能确保写日志的线程处理完所有队列中的日志才结束呢?
那得看你的主线程的程序是怎么结束了,看你的描述我猜测你现在的做法是:你在主线程中处理你的业务逻辑,然后业务逻辑会产生一些日志,然后直接往类库中的队列中发送日志消息,然后你再另起一个子线程来读取队列中的日志数据并写到文件中,然后你担心的问题是:当你的主线程产生的日志数据很快很多时,日志队列会有消息堆积,导致子线程无法第一时间把队列中的日志数据都写到本地,当你主线程所在的程序结束了之后,未写完的日志数据就丢失了。
如果这三者都是在同一个进程,然后你的结束方法是粗暴地杀死进程,那么无论如何你也避免不了的。如果你想数据不丢失,或者影响降到最小,你可以不要异步写日志,而是同步写,即是直接在主线程处理逻辑时就把日志写下来,这样即使你的进程突然挂掉,你丢失的也只是当前正在处理的逻辑的日志。
如果要做异步写,可以考虑把日志的接收和输出做到同一个进程中,主业务逻辑在另一个进程,然后主业务所在的进程直接向日志进程发送消息就行了,即使主业务的进程挂掉了也不会影响日志数据。这也是现在流行的消息队列组件(简称MQ),现在常用的MQ有RabbitMQ、Kafka、RocketMQ等,你可以去了解一下。
是的,你理解了我的问题。我之前一直在想的问题就是在同一个进程中怎么去控制。
我主要是担心同步记录日志会受到硬盘IO阻塞。
理想的办法也就是收日志写日志放到另外的进程去处理。
但有个疑问就是按你的意思讲,一些比较有名的log类库,像nlog他们也是会存在丢一部分日志的问题吗。
每次从队列取数据,队列没数据了,就可以确认结束了
Java
Runtime下有一个函数:
public void addShutdownHook(Thread hook)
注册一个线程,在结束时使用。
可以一试。