4.5学习
如何编写一次性任务
模拟 1000 万个用户,再去查询
- 用可视化界面:适合一次性导入、数据量可控
- 写程序:for 循环,建议分批,不要一把梭哈(可以用接口来控制)要保证可控、幂等,注意线上环境和测试环境是有区别的导入 1000 万条,for i 1000w
- 执行 SQL 语句:适用于小数据量
for循环插入数据库的问题:
1.建立和释放数据库连接(批量查询解决batch)
2.for循环是绝对线性的,上一条卡住下面就不会执行(并发解决)
并发要注意执行的先后顺序,不要用到非并发类的集合
`
//CPU密集型 核心线程数=CPU - 1
//IO密集型 分配的线程数可以大于CPU核数,下面的这个是数据库在进行插入属于IO密集型
public class InsertUsersTest {
@Resource
private UserService userService;
考点 默认的线程数是多少,最大的线程数是多少,什么情况下会超过40(任务达到10000《=new ArrayBlockingQueue<>(10000),任务队列满了,需要更多的线程,就会慢慢增加到1000.如果增加到1000线程还是有很多任务,可以选择任务策略)
private ExecutorService executorService = new ThreadPoolExecutor(40, 1000, 10000, TimeUnit.MINUTES, new ArrayBlockingQueue<>(10000));
@Test
public void doInsertUsers() {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
long insertNum=100000;
List<User> userList=new ArrayList<User>();
for(int i=0;i<insertNum;i++) {
User user=new User();
user.setUsername("李白");
user.setUserAccount("libai");
user.setAvatarUrl("https://www.keaitupian.cn/cjpic/frombd/0/253/2607983581/3605514878.jpg");
user.setGender(0);
user.setUserPassword("12345678");
user.setPhone("123");
user.setEmail("123@qq.com");
user.setTags("[]");
user.setUserStatus(0);
user.setUserRole(0);
user.setPlanetCode("11111111");
userList.add(user);
}
// 20 秒 10 万条
userService.saveBatch(userList, 10000);
stopWatch.stop();
System.out.println(stopWatch.getTotalTimeMillis());
}
@Test
public void doConcurrencyInsertUsers() {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
int batchSize = 5000;
int j = 0;
List<CompletableFuture<Void>> futureList = new ArrayList<>();
//20个任务
for (int i = 0; i < 20; i++) {
List<User> userList = new ArrayList<>();
while (true) {
j++;
User user=new User();
user.setUsername("李白");
user.setUserAccount("libai");
user.setAvatarUrl("https://www.keaitupian.cn/cjpic/frombd/0/253/2607983581/3605514878.jpg");
user.setGender(0);
user.setUserPassword("12345678");
user.setPhone("123");
user.setEmail("123@qq.com");
user.setTags("[]");
user.setUserStatus(0);
user.setUserRole(0);
user.setPlanetCode("11111111");
userList.add(user);
if (j % batchSize == 0) {
break;
}
}
// 异步执行
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
System.out.println("threadName: " + Thread.currentThread().getName());
userService.saveBatch(userList, batchSize);
}, executorService);
futureList.add(future);
}
CompletableFuture.allOf(futureList.toArray(new CompletableFuture[]{})).join();
stopWatch.stop();
System.out.println(stopWatch.getTotalTimeMillis());
}
}
`
点击查看代码
public class Main{
public static void main(String[] args){
Scanner sc =new Scanner(System.in);
int n=sc.nextInt();
int[] a=new int[n];
for(int i=0;i<n;i++) {
a[i]=sc.nextInt();
}
int l1=sc.nextInt();
int r1=sc.nextInt();
int l2=sc.nextInt();
int r2=sc.nextInt();
if(r1<=l2) {
for(int i=l1;i<r1;i++) {
System.out.print(a[i]+" ");
}
if(r1<l2) {
System.out.print(a[r1]+" ");
}
}else if(l1<=l2&&l2<=r1&&r2>=r1){
if(l1==l2) {
System.out.println("void");
}else {
for(int i=l1;i<l2;i++) {
System.out.print(a[i]+" ");
}
}
}else if(l2<=l1&&l1<=r2&&r1>=r2){
if(r1==r2) {
System.out.println("void");
}else {
for(int i=r2+1;i<=r1;i++){
System.out.print(a[i]+" ");
}
}
}else if(l1<=l2&&r2<=r1){
for(int i=l1;i<l2;i++) {
System.out.print(a[i]+" ");
}
for(int i=r2+1;i<=r1;i++) {
System.out.print(a[i]+" ");
}
}else if(l2<=l1&&r1<=r2) {
System.out.print("void");
}
}
}
7-7 数组区间差集A-B
分数 10
作者 zzuli
单位 郑州轻工业大学
输入一个整数数组(题目保证数组中的整数不重复),然后输入两个闭区间,区间A[L1, R1]和区间B[L2, R2],L1, R1代表区间A的左/右边界的数组下标;L2, R2代表区间B的左/右边界的数组下标(下标从0开始,且题目保证下标均在有效范围内不会越界)。输出由这两个区间形成的差集(A-B)的数值。
输入格式:
一个整数n(n不大于20),然后输入n个整数。
最后输入4个整数,分别代表区间A和区间B的左边界和右边界的下标,顺序为:L1 R1 L2 R2
输出格式:
按原数组的顺序依次输出两个区间差集(A-B)中的数值,每个数值后面一个空格。
如果是空集,则输出void
输入样例:
20 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 0 9 4 12
输出样例:
11 12 13 14
所有区间情况

按照图写出所有区间情况
由于数组中不存在重复的数值,可以用Set来处理区间B,找到在A中而不在B中的集合会更方便
List<Integer> result = new ArrayList<>(); for (int num : listA) { if (!setB.contains(num)) { result.add(num); } }

浙公网安备 33010602011771号