netty提供了高效的线程安全的队列 MpscArrayQueue ,一个字快,至于快的原因可以去查看相关的文章,内存的伪共享先关的内容.
import static java.lang.Thread.sleep;
import io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueue;
import java.util.ArrayList;
import java.util.List;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 日志服务
*
* @author wyzhang
* @date 2021/1/11 16:09
*/
@Slf4j
@Service
public class LogService<T> {
MpscArrayQueue<T> mpscArrayQueue = new MpscArrayQueue(10000);
@SneakyThrows
public void addLog(T content) {
boolean offer = mpscArrayQueue.offer(content);
if (!offer) {
log.info("写入日志失败{}", content);
sleep(1);
}
}
public List<T> drain() {
List<T> list = new ArrayList<>();
mpscArrayQueue.drain(
(e) -> {
list.add(e);
},
100);
return list;
}
}
测试代码
@Test
public void testMpsQueue() throws InterruptedException {
final LogService<String> logService = new LogService();
AtomicInteger atomicInteger = new AtomicInteger(0);
Runnable supplier =
new Runnable() {
@SneakyThrows
@Override
public void run() {
while (true) {
String content= "data is " + atomicInteger.incrementAndGet();
// log.info("写入数据 {}" , content);
logService.addLog(content);
sleep(1);
}
}
};
Thread t1 = new Thread(supplier);
t1.start();
Thread t2 = new Thread(supplier);
t2.start();
new Thread(
() -> {
while (true) {
List<String> list = logService.drain();
log.info(" data length is {} data is {}", list.size(), list);
if (CollectionUtils.isEmpty(list)) {
try {
sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
})
.start();
while (true) {
sleep(1000);
t1.stop();
t2.stop();
sleep(20);
break;
}
}