线程池的创建
一、创建线程的方式:
- Thread子类
- Runnable
- 使用线程池(重点)
提供系统的吞吐量的做法:
线程池>redis缓存(消耗io次数)>把同步拆成异步>服务拆分 服务的冗余部署>冗余部署的服务器+机器配置
分库分表的知识
mysql数据库。分表:数据量达到500万以上,那就要分表了。分库:订单库单独的mysql,库存库单独的mysql,一个服务一个数据库。
订单表中的数据达到500万以上。就要分表,分成1024表,500万%1024=0-1023。
1.jdk官方提供的四种创建线程池的方式:
//创建了只有一条线程的线程池,内存溢出: 阻塞队列过长,Integer.MAX_VALUE 21亿
ExecutorService pool = Executors.newSingleThreadExecutor();
//创建了有五条线程的线程池 内存溢出: 阻塞队列过长,Integer.MAX_VALUE 21亿
ExecutorService executorService = Executors.newFixedThreadPool(5);
//创建了一个线程池,根据内存的大小,决定里面线程的条数,如果内存不够,就不会再有新的线程(内存溢出:最大线程数过大)。如果内存够,有新的请求来,不需要等待,会创建新的线程。
ExecutorService executorService1 = Executors.newCachedThreadPool();
//创建与定时任务有关的线程池。 内存溢出:最大线程数过大
ExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
这四种方式都会造成内存溢出。

public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
2.线程池的核心参数
ThreadPoolExecutor:
* 第一个参数: 核心线程数 当线程池创建出来后,线程池中线程的数量
* 第二个参数: 最大线程数 当请求进入到阻塞队列,阻塞队列放满后,然后线程池会创建出新到线程,直到达到最大线程数。
* 第三个参数: 发呆时间 当新创建的线程空闲多少时间后会被回收。
* 第四个参数: 发呆时间单位
* 第五个参数: 阻塞队列,阻塞队列满了,创建新的线程,如果达到最大线程数,就执行抛弃策略
3.如何创建线程池
用官方的方式创建的线程池会造成内存溢出。
//这个线程池才会不会有内存溢出。
ThreadPoolExecutor pool = new ThreadPoolExecutor(
coreNum, //核心线程池
coreNum * 2,//最大线程数
20L, //发呆时间
TimeUnit.MILLISECONDS,
new LinkedBlockingDeque<Runnable>(1000) //阻塞队列
);
具体实现:
package com.qf.es.demo.threadpool;
import com.qf.es.demo.entity.Person;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
public class TestThreadPool {
/**
* 如何创建线程池
*
*
*
*
* public static ExecutorService newSingleThreadExecutor() {
* return new FinalizableDelegatedExecutorService
* (new ThreadPoolExecutor(1, 1,
* 0L, TimeUnit.MILLISECONDS,
* new LinkedBlockingQueue<Runnable>()));
* }
*
*
* ThreadPoolExecutor:
* 第一个参数: 核心线程数 当线程池创建出来后,线程池中线程的数量
* 第二个参数: 最大线程数 当请求进入到阻塞队列,阻塞队列放满后,然后线程池会创建出新到线程,直到达到最大线程数。
* 第三个参数: 发呆时间 当新创建的线程空闲多少时间后会被回收。
* 第四个参数: 发呆时间单位
* 第五个参数: 阻塞队列
*
* //创建了只有一条线程的线程池
* ExecutorService pool = Executors.newSingleThreadExecutor();
* //创建了有五条线程的线程池
* ExecutorService executorService = Executors.newFixedThreadPool(5);
* //创建了一个线程池,根据内存的大小,决定里面线程的条数,如果内存不够,就不会再有新的线程。如果内存够,有新的请求来,不需要等待,会创建新的线程。
* ExecutorService executorService1 = Executors.newCachedThreadPool();
* //创建与定时任务有关的线程池。
* ExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
*/
@Test
public void testThread() throws ExecutionException, InterruptedException {
//获取当前机器的cpu核数 系统级线程 用户级线程
int coreNum = Runtime.getRuntime().availableProcessors();
//这个线程池才会不会有内存溢出。
ThreadPoolExecutor pool = new ThreadPoolExecutor(
coreNum, //核心线程池
coreNum * 2,
20L,
TimeUnit.MILLISECONDS,
new LinkedBlockingDeque<Runnable>(1000)
);
//用线程池来批量新增用户, 用户一共有1000000条,如果用单线程 dao.insert(person),
List<Person> persons = new ArrayList<>();
Person p1 = new Person(1L,"xiaowang",20,"");
Person p2 = new Person(1L,"xiaowang",20,"");
Person p3 = new Person(1L,"xiaowang",20,"");
Person p4 = new Person(1L,"xiaowang",20,"");
Person p5 = new Person(1L,"xiaowang",20,"");
Person p6 = new Person(1L,"xiaowang",20,"");
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
persons.add(p5);
persons.add(p6);
for (Person person : persons) {
//dao.insert(person)
// pool.submit(new MyRunnbale(person));
Future<String> submit = pool.submit(new MyCallable(person));
System.out.println(submit.get());
}
System.out.println("线程池的任务已经结束");
}
}

浙公网安备 33010602011771号