JUC包–BlockingQueue的使用样例
系统中有业务需要实现队列,引入中间件又没有太大必要,因此直接使用jdk自带的类,之前也未使用过,因此将使用的类记录下,以供后边当工具类使用。在新增的Concurrent包中,BlockingQueue(就是个队列而已)很好的解决了多线程中数据的安全问题。
线程操作类
@Component
@Slf4j
public class FlowQueue implements Runnable {
private final BlockingQueue<FlowRequest> queue = new LinkedBlockingQueue<>();
private final FlowHandler flowHandler;
public FlowQueue(FlowHandler flowHandler) {
this.flowHandler = flowHandler;
}
//请求加入队列的方法
public void submitRequest(FlowRequest flowRequest) {
try {
queue.put(flowRequest);
} catch (InterruptedException e) {
log.error("Failed to submit flow request, queue interrupted", e);
}
}
//队列执行的方法
@Override
public void run() {
try {
FlowRequest take;
//使队列处于监控状态
while (!Thread.interrupted() && (take = queue.take()) != null) {
flowHandler.accept(take);
}
} catch (InterruptedException e) {
log.error("FlowQueue terminated, due to below", e);
}
}
//从队列中移除某请求
public void removeRequest(FlowRequest flowRequest) {
queue.remove(flowRequest);
}
//项目启动时就启动该线程进行监控
@PostConstruct
public void init() {
new Thread(this).start();
}
}
线程处理业务类
@Component
@Slf4j
public class FlowHandler implements Consumer<FlowRequest> {
private XxxxxDao xxxxxDao;
//多线程中无法使用autowired或者resource就行注入,故采用构造器注入Dao,Service等
public FlowHandler(XxxxxDao xxxxxDao){
this.xxxxxDao = xxxxxDao;
}
@Override
public void accept(FlowRequest flowRequest) {
//todo
//需要线程处理的业务,具体参数可以封装到FlowRequest类中,也可以使用其他参数,这里仅供参考
}else {
log.info("");
}
}
}
几个常用操作的API
- 入队
- put(E e):如果队列满了,一直阻塞,直到队列不满了或者线程被中断–>阻塞
- offer(E e):如果队列没满,立即返回true; 如果队列满了,立即返回false–>不阻塞
- 出队
- poll():如果没有元素,直接返回null;如果有元素,出队
- take():如果队列空了,一直阻塞,直到队列不为空或者线程被中断–>阻塞
此处只是使用了LinkedBlockingQueue,此外家族中还有一些其他的成员,有需要时可以再研究下,网上参考的图片