线程池的创建

一、创建线程的方式:

  • 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);

这四种方式都会造成内存溢出。

image-20210429095925556

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("线程池的任务已经结束");


    }

}

posted @ 2021-07-22 11:31  牛奶配苦瓜  阅读(147)  评论(0)    收藏  举报