1. 场景:
通过Jmeter 调用接口 将数据 添加到队列中然后, 再消费队列, 批量插入数据库
2. 代码
项目结构
类:ApplicationQueue
package com.wudl.queue.config;
import com.wudl.queue.domain.User;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* @author :wudl
* @date :Created in 2021-12-12 22:08
* @description:
* @modified By:
* @version: 1.0
*/
public class ApplicationQueue {
//队列大小
static final int QUEUE_MAX_SIZE = 1000;
static BlockingQueue<User> blockingQueue = new LinkedBlockingQueue<User>(Integer.MAX_VALUE);
/**
* 私有的默认构造子,保证外界无法直接实例化
*/
private ApplicationQueue() {
}
;
/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
* 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
*/
private static class SingletonHolder {
/**
* 静态初始化器,由JVM来保证线程安全
*/
private static ApplicationQueue queue = new ApplicationQueue();
}
//单例队列
public static ApplicationQueue getMailQueue() {
return SingletonHolder.queue;
}
//生产入队
public void produce(User mail) throws InterruptedException {
blockingQueue.put(mail);
}
//消费出队
public User consume() throws InterruptedException {
return blockingQueue.take();
}
// 获取队列大小
public int size() {
return blockingQueue.size();
}
}
线程MyAppThreadFactory
package com.wudl.queue.config;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author :wudl
* @date :Created in 2021-12-12 22:49
* @description:
* @modified By:
* @version: 1.0
*/
public class MyAppThreadFactory {
/**
* 线程池执行器 Executors 首选的线程池
* ExecutorService executorService=Executors.newCachedThreadPool();
*/
public static ExecutorService myCachedThreadPool= new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>());
}
消费者
package com.wudl.queue.config;
import com.wudl.queue.domain.User;
import com.wudl.queue.service.UserService;
import lombok.Synchronized;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* @author :wudl
* @date :Created in 2021-12-12 22:26
* @description:
* @modified By:
* @version: 1.0
*/
@EnableScheduling // 1.开启定时任务
@EnableAsync // 2.开启多线程
@Component
public class UserConsume {
@Autowired
UserService userService;
List<User> list = new LinkedList<>();
int number = 0;
public synchronized void run() throws Exception {
while (true) {
User consume = null;
try {
consume = ApplicationQueue.getMailQueue().consume();
FileWriter fw = new FileWriter("D:\\tmp\\CCCC.txt", true);
BufferedWriter bw = new BufferedWriter(fw);
bw.append("消费-->");
bw.write(consume.toString() + "\r\n ");
bw.close();
fw.close();
} catch (InterruptedException e) {
e.printStackTrace();
}
list.add(consume);
if (list.size() >=10)
{
List<User> strsSync = Collections.synchronizedList(list);
userService.insertBatch(strsSync);
System.out.println(list.size());
list.clear();
}
}
}
private static String lock = "";
@Synchronized
@Scheduled(fixedDelay = 100) //间隔1秒
public void cleanRankListJobExecute() throws Exception {
User consume = ApplicationQueue.getMailQueue().consume();
MyAppThreadFactory.myCachedThreadPool.execute(()->
{
});
try {
synchronized (lock){
run();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
接口
package com.wudl.queue.controller;
import com.wudl.queue.domain.User;
import com.wudl.queue.service.UserService;
import com.wudl.queue.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
/**
* @author :wudl
* @date :Created in 2021-12-12 20:49
* @description:控制层
* @modified By:
* @version: 1.0
*/
@RestController
public class UserController {
// @Autowired
// Producer producer;
private static String lock = "";
@Autowired
UserService userService;
int i = 0;
@GetMapping("/user/findall")
public List<User> findall() throws Exception {
List<User> all = userService.findAll();
return all;
}
@GetMapping("/user/addUser")
public String addUser() throws Exception {
User u = new User();
u.setId(9);
u.setUserNo("100014");
u.setUserName("myhdfs");
userService.addUser(u);
return "success";
}
@GetMapping("/user/insertBatch")
public String insertBatch() throws Exception {
i++;
User u = new User();
u.setId(9);
u.setUserNo("100014"+i);
u.setUserName("myFlink"+i);
userService.insertBatchTow(u);
FileWriter fw = new FileWriter("D:\\tmp\\x.txt", true);
BufferedWriter bw = new BufferedWriter(fw);
bw.append("消费-->"+i);
bw.write(u.toString() + "\r\n ");
bw.close();
fw.close();
return "success";
}
}
实体类
package com.wudl.queue.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author :wudl
* @date :Created in 2021-12-22 22:50
* @description:
* @modified By:
* @version: 1.0
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String userName;
private String userNo;
}
持久层
package com.wudl.queue.mapper;
import com.wudl.queue.domain.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @author :wudl
* @date :Created in 2021-12-22 22:51
* @description:
* @modified By:
* @version: 1.0
*/
@Mapper
public interface UserMapper
{
/**
* 查询所有
* @return
*/
List<User> findAll();
void addUser(User user);
void insertBatch(List<User> list);
}
接口实现
package com.wudl.queue.service.impl;
import com.wudl.queue.config.ApplicationQueue;
import com.wudl.queue.domain.User;
import com.wudl.queue.mapper.UserMapper;
import com.wudl.queue.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author :wudl
* @date :Created in 2021-12-12 22:12
* @description:
* @modified By:
* @version: 1.0
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
// @Override
// public void sendQueue(User user) throws Exception {
// MailQueue.getMailQueue().produce(user);
//
// }
@Override
public List<User> findAll() {
return userMapper.findAll();
}
@Override
public void addUser(User user) {
userMapper.addUser(user);
}
@Override
public void insertBatch(List<User> list) {
userMapper.insertBatch(list);
}
@Override
public void insertBatchTow(User list) throws InterruptedException {
ApplicationQueue.getMailQueue().produce(list);
// userMapper.insertBatch(list);
}
}
接口
package com.wudl.queue.service;
import com.wudl.queue.domain.User;
import java.util.List;
/**
* @author :wudl
* @date :Created in 2021-12-12 22:11
* @description:
* @modified By:
* @version: 1.0
*/
public interface UserService {
// public void sendQueue(User user) throws Exception;
public List<User> findAll();
void addUser(User user);
void insertBatch(List<User> list);
void insertBatchTow(User list) throws InterruptedException;
}
package com.wudl.queue.utils;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* @author :wudl
* @date :Created in 2021-12-12 21:47
* @description:
* @modified By:
* @version: 1.0
*/
public class BlockingQueueMessage {
public static BlockingQueue<String> queue = new LinkedBlockingQueue<>(5);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wudl.queue.mapper.UserMapper">
<select id="findAll" resultType="com.wudl.queue.domain.User">
select * from user
</select>
<insert id="addUser" parameterType="com.wudl.queue.domain.User">
INSERT INTO user (id,userNo,userName) VALUE(#{id},#{userNo},#{userName})
</insert>
<!-- 批量插入 -->
<insert id ="insertBatch" parameterType="java.util.List" >
insert into user
(userNo,userName)
values
<foreach collection ="list" item="u" index= "index" separator =",">
(
#{u.userNo},
#{u.userName}
)
</foreach >
</insert >
</mapper>
spring:
datasource:
#数据源基本配置
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.180:3306/test?serverTimezone=UTC
type: com.alibaba.druid.pool.DruidDataSource
#数据源其他配置
druid:
#配置初始化大小、最小、最大线程数
initialSize: 5
minIdle: 5
#CPU核数+1,也可以大些但不要超过20,数据库加锁时连接过多性能下降
maxActive: 20
#最大等待时间,内网:800,外网:1200(三次握手1s)
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
#配置一个连接在池中最大空间时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
#设置从连接池获取连接时是否检查连接有效性,true检查,false不检查
testOnBorrow: true
#设置从连接池归还连接时是否检查连接有效性,true检查,false不检查
testOnReturn: true
#可以支持PSCache(提升写入、查询效率)
poolPreparedStatements: true
#配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,log4j
#保持长连接
keepAlive: true
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
#整合mybatis
mybatis:
#配置别名
type-aliases-package: com.wudl.queue.domain
#配置 xml 文件映射 classpath: = resources /=当前项目下
mapper-locations: classpath:mapper/*.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wudl-LinkedBlockingQueue</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>
插入结果:100万数据 一条没有丢