ConcurrentLinkedQueue 是非阻塞队列
概念
并编程中,一般需要用到安全的队列,如果要自己实现安全队列,可以使用2种方式:
方式1:加锁,这种实现方式就是我们常说的阻塞队列。
方式2:使用循环CAS算法实现,这种方式实现队列称之为非阻塞队列。
非阻塞队列经典实现类:ConcurrentLinkedQueue (JDK1.8版)
业务场景:
审批流程:
当发起审批流程时,需要调用钉钉接口,钉钉接口推送任务给用户,用户审批。
调用钉钉接口时耗费的时间比较长,所以把调用接口这块放到ConcurrentLinkedQueue这里实现。
先把审批流程的id通过add放到队列里,然后在用异步线程去队列里取出id,然后再调用钉钉接口。
以下是我的实现的类:
我的项目是基于srpingboot。
实现步骤如下:
1.写一个线程类TaskThread继承Thread。这个类是启动线程,从队列里取出数据执行。
2.在springboot启动类去启动这个TaskThread类。
3.创建一个任务类Task,里面只有一个run方法。这个类的作用是便于具体实现类来继承。
4.再创建一个具体实现的任务类ProcessTask,来实现run方法,在这里写具体的操作。
5.在controlloer里具体使用的类DingTalkController。
代码如下:
**import java.util.concurrent.ConcurrentLinkedQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component(value = "taskThread")
public class TaskThread extends Thread{
Logger logger = LoggerFactory.getLogger(TaskThread.class);
private ConcurrentLinkedQueue<Task> taskQueue;
private boolean _stop = false;
public TaskThread(){
taskQueue = new ConcurrentLinkedQueue<>();
}
public void addTask(Task task){
taskQueue.add(task);
}
public void setStop(){
synchronized (taskQueue){
_stop = true;
taskQueue.notify();
}
}
@Override
public void run(){
logger.info("线程已启动");
synchronized (taskQueue){
while (!_stop){
if(!taskQueue.isEmpty()){
Task task = taskQueue.poll();
if(task != null){
try{
task.run();
}catch (Exception e){
e.printStackTrace();
}
}else {
try {
taskQueue.wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}**
public class WsqfApplication {
public static ConfigurableApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext = SpringApplication.run(WsqfApplication.class, args);
//开启线程
TaskThread taskThread = (TaskThread) applicationContext.getBean("taskThread");
taskThread.start();
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.thunisoft.wsqf.controller.WsqfController;
import com.thunisoft.wsqf.dingtalk.service.DingTalkService;
import com.thunisoft.wsqf.utils.BaseResult;
@Component("processTask")
@Scope("prototype") //表示每次获得bean都会生成一个新的对象
public class ProcessTask implements Task {
Logger logger = LoggerFactory.getLogger(ProcessTask.class);
@Autowired
private WsqfController wsqfController;
@Autowired
private DingTalkService dingTalkService;
private String taskId;
private String type;
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public void run() {
try{
logger.info("流程任务start_"+this.getTaskId());
String processId = this.getTaskId();
JSONObject paramJson = new JSONObject();
paramJson.put("processId", processId);
getUnfinishProcessTask(paramJson,this.getType());
logger.info("流程任务end_"+this.getTaskId());
}catch (Exception e){
//获取代办任务失败,把processId保存到表里
logger.info(e.getMessage());
}
}
/**
*获取代办任务
* @param json
*/
public void getUnfinishProcessTask(JSONObject json,String type){
logger.info("内网拉取待办任务: processId="+json.getString("processId"));
BaseResult baseResult = wsqfController.apis("lczxTaskList", json.toString());
if(baseResult.getCode().equals("200")){
JSONObject data = new JSONObject();
if(baseResult.getObj() != null){
data = JSONObject.parseObject(baseResult.getObj().toString());
}
if("create".equals(type)) {
logger.info("钉钉流程begin");
dingTalkService.dingTalkProcessNotice(json.getString("processId"),data,"start");
logger.info("钉钉流程end");
}else {
logger.info("更新钉钉待办任务begin");
dingTalkService.dingTalkProcessNotice(json.getString("processId"),data,"update");
logger.info("更新钉钉待办任务end");
}
} else { //如果调用内网失败了保存流程实例id到流程表里
dingTalkService.insertProcessInfoOne(json.getString("processId"));
}
}
}
**@RestController
@RequestMapping("/api/v2/")
public class DingTalkController {
private static Logger logger = LoggerFactory.getLogger(DingTalkController.class);
@Autowired
private TaskThread taskThread;
@Autowired
private ProcessTask processTask;
@PostMapping("dingtalk")
public BaseResult callDingTalks(@RequestBody JSONObject json) {
String methodName = json.getString("methodName");
JSONObject resJson = JSONObject.parseObject(json.getString("data"));
logger.info("内网应用调用钉钉接口开始。。。。。");
String processId = resJson.getString("processId");
if (methodName.equals(DingEnum.createDingTalkProcess.name())) {//开启钉钉流程
logger.info("内网发送的processId="+processId);
processTask.setTaskId(processId);
processTask.setType("create");
taskThread.addTask(processTask);
return new BaseResult("200","获取流程实例id成功",null);
}else if(methodName.equals(DingEnum.updateWorkrecordTask.name())) {//更新钉钉待办任务
logger.info("内网发送的processId="+processId);
processTask.setTaskId(processId);
processTask.setType("update");
taskThread.addTask(processTask);
return new BaseResult("200","获取流程实例id成功",null);
}
return new BaseResult("500","接收信息出错");
}
}**