服务的生命周期大于或等于所包含的线程的生命周期,一定要考虑线程的关闭导致的结果。
版本一
class LogWriter {
private BlockingQueue<String> queue = new LinkedBlockingQueue<>();
private LogThread thread = new LogThread();
private class LogThread extends Thread {
@Override
public void run() {
while (true) {
try {
System.out.println(queue.take());
} catch (InterruptedException e) {
// 不处理
System.out.println("-- InterruptedException");
}
}
}
}
public void start() {
thread.start();
}
public void log(String msg) {
queue.offer(msg);
}
}
- 没有完备的线程退出关闭机制,可能导致消息丢失
版本二
class LogWriter {
private BlockingQueue<String> queue = new LinkedBlockingQueue<>();
private LogThread thread = new LogThread();
private volatile boolean isShutDown = false;
private AtomicInteger reservations = new AtomicInteger();
private class LogThread extends Thread {
@Override
public void run() {
// 保证所有msg都能持久化到硬盘上
while (isShutDown && reservations.get() == 0) {
try {
System.out.println(queue.take());
reservations.addAndGet(-1);
} catch (InterruptedException e) {
System.out.println("-- InterruptedException");
}
}
}
}
public void start() {
reservations.set(0);
thread.start();
}
public void log(String msg) {
if (isShutDown) {
throw new IllegalStateException("logThread stop.");
}
reservations.addAndGet(1);
queue.offer(msg);
}
public void stop() {
isShutDown = true;
thread.interrupt();
}
}
- 使用原子整形保证剩余数量的并发安全。
版本三
使用线程池进行线程任务的管理,使用shutdown()或者shutdownNow进行管理
版本四
毒丸对象:往消息队列里加入终止标记,如果执行到“毒丸 - 终止标记”,则线程关闭。
– 仅适用于数量不大的情况下。