java实现接收MQ消息后加入内存队列进行消费
根据appSampleId进行区分,相同id的采用同一个线程去处理。
ConcurrentHashMap、ConcurrentLinkedQueue 都是线程安全的
最多采用10个线程进行消费。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import static java.util.concurrent.Executors.*;
/**
* @ClassName: demo
* @Author: pjl
* @Description:
* @Date: 2021/12/22
*/
@Component
@RestController
public class demo {
//定义内存队列
private static Map<String, ConcurrentLinkedQueue> map = new ConcurrentHashMap<>();
public static ExecutorService executorService= newFixedThreadPool(10);
static class data{
private String id;
private String appSampleId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAppSampleId() {
return appSampleId;
}
public void setAppSampleId(String appSampleId) {
this.appSampleId = appSampleId;
}
@Override
public String toString() {
return "data{" +
"id='" + id + '\'' +
", appSampleId='" + appSampleId + '\'' +
'}';
}
}
public static void consumer(){
List<data> dataList=new ArrayList<data>();
for (int i=0;i<100;i++){
//模拟100条数据
data d=new data();
d.setId(i+"");
d.setAppSampleId((Math.round(Math.random()*20))+"");
dataList.add(d);
}
for (data d:dataList){
//如果map中没有此appSampleId
synchronized (demo.class){
//如果map中没有此appSampleId
if(!map.containsKey(d.getAppSampleId())){
ConcurrentLinkedQueue<data> concurrentLinkedQueue=new ConcurrentLinkedQueue();
concurrentLinkedQueue.add(d);
map.put(d.getAppSampleId(),concurrentLinkedQueue);
executorService.execute(() -> {
// System.out.println(Thread.currentThread().getName()+"开始执行");
//执行任务,开始消费
while (!map.get(d.getAppSampleId()).isEmpty()){
//如果队列不为空则消费
data d1= map.get(d.getAppSampleId()).poll();
//模拟消费
System.out.println(d1.toString());
}
map.remove(d.getAppSampleId());
});
//runMethod(d);
}else {
//如果map中有此appSampleId
map.get(d.getAppSampleId()).offer(d);
}
}
}
}
public static void main(String[] args) {
consumer();
}
@GetMapping("/asc")
public void test(){
consumer();
}
@Async("taskExecutor")
public static void runMethod(data d){
//执行任务
ConcurrentLinkedQueue queue = map.get(d.getAppSampleId());
while (!queue.isEmpty()){
//如果队列不为空则消费
data d1= (data) queue.poll();
//模拟消费
System.out.println(d1.toString());
}
map.remove(d.getAppSampleId());
}
@Configuration
@EnableAsync
class SpringAsyncConfig {
@Bean("taskExecutor")
public Executor asyncServiceExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(10);
// 设置最大线程数
executor.setMaxPoolSize(10);
//配置队列大小
executor.setQueueCapacity(Integer.MAX_VALUE);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置默认线程名称
executor.setThreadNamePrefix("测试");
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
//执行初始化
executor.initialize();
return executor;
}
}
}