线程池简单认识

1.线程池的作用

1.  降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 
2.  提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。 
3.  提高线程的可管理性。

2.线程池原理

这里写图片描述

分析:我们如何理解这幅图呢,以及我们可以简单对它们进行简单的模仿?

1.  核心线程池就像相当于我们互联网公司的核心成员。

2.  当任务来的时候,核心线程池进行消费,当任务比较多的时候,由产品经理把任务统计起来(就是任务队列),如果产品经理发现任务多的已经统计不过来,说明任务队列已经满了。

3.  在任务队列里面任务太多的时候,公司就会进行招聘一些外包人员,这时的线程就是核心线程以外的线程,并且会把它们放到一个线程池中,让这些外包也来完成产生的任务,但是这时候外包人员也不能处理产生的任务

4.就会产生一种策略,其实这些策略就是异常处理,在jdk提供了四种处理异常的策略

异常策略:

  •  CallerRunsPolicy:只要线程池没关闭,就直接用调用者所在线程来运行任务
  •  AbortPolicy:直接抛出 RejectedExecutionException 异常
  • DiscardPolicy:悄悄把任务放生,不做了
  • DiscardOldestPolicy:把队列里待最久的那个任务扔了,然后再调用 execute() 试试看能行不

3. jdk提供四种线程池

ThreadPoolExecutor:

分析:我们可以看到jdk里面提供的四种线程池里面最后都是调用threadpoolexecutor这个类,但是这个类里面有7个参数,分别

corePoolSize:核心线程大小(及互联网公司的核心成员)

maximumPoolSize:最大线程池的大小(外包人员)

keepAliveTime:除过核心线程池外,其他线程的存活时间。(及外包人员的存活时间)

unit:创建线程的存活时间

workQueue:任务队列,在jdk里面提供四种任务队列

  •      ArrayBlockingQueue:基于数组、有界,按 FIFO(先进先出)原则对元素进行排序
  •      LinkedBlockingQueue:基于链表,按FIFO (先进先出) 排序元素 

                吞吐量通常要高于 ArrayBlockingQueue
                Executors.newFixedThreadPool() 使用了这个队列

  •     SynchronousQueue:不存储元素的阻塞队列 

             每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态
             吞吐量通常要高于 LinkedBlockingQueue
             Executors.newCachedThreadPool使用了这个队列

  •     PriorityBlockingQueue:具有优先级的、无限阻塞队列

threadFactory:线程工厂,对线程进行管理

策略模式:出现异常时,使用的策略。

1.  newFixedThreadPool:

分析:keepAliveTime为0,说明只有核心线程池,产生的核心线程池以外的线程,它们的存活时间将变为0,那么在极端情况下,如果任务比较多的话,会很快使任务队列已满,可以用于负载比较重的服务器

2.  newSingleThreadExecutor:

分析:是上面newFixThreadPool的一个特例,里面核心线程只有一个,没有其他多余的线程, 用于串行执行任务的场景,每个任务必须按顺序执行,不需要并发执行。

3.  newCachedThreadPool:

分析:可以看出corePoolSize的大小为0,可以说全是外包,极端情况下会创建过多的线程,耗尽 CPU 和内存资源。

CachedThreadPool 用于并发执行大量短期的小任务,或者是负载较轻的服务器。

4.  newScheduledThreadPool:

分析:ScheduledThreadPoolExecutor 用于需要多个后台线程执行周期任务,同时需要限制线程数量的场景。

4.简单模仿线程池

1.  首先一定这个线程池的行为规范有哪些

  •      执行线程的接口
  •     得到当前任务队列(这个任务队列就是池子,让生产者生产任务,让消费者任务)里面的任务数量
  •     得到当前任务队列里面已经消费的任务数量
  •     得到当前的工作线程数量

2.  定义ThreadManagePool这个类

  •     首先需要实现ThreadPool的行为规范
  •     需要定义消费者类,这个类主要是消费任务,但是必须把它和生产者结合起来,它必须只要什么时候需要消费,在这里使用一个链表,把两者结合起来,消费者必须每一次检查链表是不是空,如果是空的,就进行等待,直到链表不为空,进行消费。
  • 销毁线程,首先要检查任务队列里面的任务是否消费完毕,如果没有完毕进行等待处理,如果消费完毕,关闭每一个消费者,在关闭线程池。

public class ThreadManagePool implements ThreadPool {

    //默认工作线程个数
    private static int workerNum = 5;

    //工作线程数量
    public WorkThread[] workThreads;

    //执行任务数量
    private static volatile int executeTaskNumber = 0;

    private static ThreadManagePool threadManagePool;

    private List<Runnable> taskQueue = new LinkedList<Runnable>();

    private ThreadManagePool(){
        this(workerNum);
    }

    private ThreadManagePool(int workerNum){
        if(workerNum > 0) {
            ThreadManagePool.workerNum = workerNum;
        }
        //工作线程的初始化
        workThreads = new WorkThread[workerNum];

        for(int i = 0;i<ThreadManagePool.workerNum;i++) {
            workThreads[i] = new WorkThread();
            Thread thread = new Thread(workThreads[i]);
            System.out.println("初始化线程总数" + (i + 1) + "------当前线程名称是:" + thread.getName());
            thread.start();
        }
    }

    public static ThreadPool getThreadPool(){
       return  getTheadPool(ThreadManagePool.workerNum);
    }

    public static ThreadPool getTheadPool(int workNum){
        if(workNum <= 0) {
            workNum = ThreadManagePool.workerNum;
        }
        if(threadManagePool == null) {
            threadManagePool = new ThreadManagePool(workNum);
        }
        return threadManagePool;
    }

    /**
     * 线程池销毁
     */

    @Override
    public void destory() {

        while (!taskQueue.isEmpty()) {

            try {
                //不断检测任务队列是否全部执行
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        for (int i = 0; i < workerNum; i++) {
            workThreads[i].stopWorker();
            workThreads[i] = null;
        }

        threadManagePool = null;
        taskQueue.clear();
    }

    @Override
    public void execute(Runnable runnable) {
        synchronized (taskQueue) {
            taskQueue.add(runnable);
            //通知 启动的线程
            taskQueue.notifyAll();
        }
    }

    @Override
    public void execute(List<Runnable> runnables) {
        synchronized (taskQueue) {
            for (Runnable task : runnables) {
                taskQueue.add(task);
            }
            taskQueue.notifyAll();
        }

    }

    @Override
    public void execute(Runnable[] runnables) {
        synchronized (taskQueue) {
            for (Runnable task : runnables) {
                taskQueue.add(task);
            }
            taskQueue.notifyAll();
        }
    }

    @Override
    public int getExecuteTaskCount() {
        return executeTaskNumber;
    }

    @Override
    public int getWorkTaskCount() {
        return taskQueue.size();
    }

    @Override
    public int getWorkTheadCount() {
        return workerNum;
    }

    @Override
    public String toString() {
        return "当前工作线程数:" + workerNum +
                ", 已完成任务数:" + executeTaskNumber +
                ", 等待任务数量:" + getWorkTaskCount();
    }

    private class WorkThread extends Thread{

        //该工作线程是否有效 用于结束该工作线程
        private boolean isRunning = true;

        Runnable r = null;

        @Override
        public void run() {
            super.run();
            while(isRunning){
                synchronized (taskQueue) {
                    while(isRunning&&taskQueue.isEmpty()){
                        try {
                            taskQueue.wait(20);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    if(!taskQueue.isEmpty()) {
                        r = taskQueue.remove(0);
                    }
                    if(r!=null) {
                        r.run();
                    }
                    executeTaskNumber++;
                    r = null;
                }
            }
        }

        //停止工作 让该线程自然执行完run方法 自然结束
        public void stopWorker() {
            isRunning = false;
        }
    }

}
public class ThreadTest {

    public static void main(String[] args) {
        ThreadPool t = ThreadManagePool.getTheadPool(6);

        List<Runnable> taskList = new ArrayList<Runnable>();

        for (int i = 0; i < 10; i++) {
            taskList.add(new task());
        }
        t.execute(taskList);
        System.out.println(t);
        t.destory();//所有线程执行完才destory
        System.out.println(t);

    }

    //任务类
    public static class task implements Runnable{
        private static volatile int i = 1;
        @Override
        public void run() {
            System.out.println("当前处理的线程是:" + Thread.currentThread().getName() + " 执行任务" + (i++) + " 完成");
        }
    }

}

分析:发现虽然我们初始化许多线程,但是只有一个线程在消费队列里面的任务,主要是因为使用的同一把锁,一次只能让一个线程进入进行消费,是一个串行的过程,有点像jdk里面的singleNewThreadPool这个线程池,还有问题就是我们解耦,通过链表把消费者和生成者联系起来,所以我们应该用一个工具来管理线程,这个类ThreadFactory。

2. 对上述代码进行解耦处理

ThreadFactory类代码:

package com.mec.test;


import java.util.LinkedList;
import java.util.List;

public  class ThreadFactory  {

    //管理线程
    private static List<WorkThread> workThreads = new LinkedList<WorkThread>();

    //任务队列
    private static List<Runnable> workTask = new LinkedList<Runnable>();

    private static  boolean flag = true;

    private volatile static int executeTaskNumber =0;

    //使用单例模式
    private ThreadFactory(){};

    //添加任务
    public static void addWorkTask(Runnable runnable){
        synchronized (workTask){
            workTask.add(runnable);
            workTask.notifyAll();
        }
    }

    //添加任务
    public static void addWorkTask(List<Runnable> runnables){
        synchronized (workTask){
            for(Runnable runnable : runnables){
                workTask.add(runnable);
            }
            workTask.notifyAll();
        }

    }

    //添加任务
    public static void addWorkTask(Runnable[] runnables){
        synchronized (workTask){
            for(Runnable runnable : runnables){
                workTask.add(runnable);
            }
            workTask.notifyAll();
        }
    }

    //初始化工作线程
    public static  void initWorkThread(int initCount){
        if(initCount<0){
            return;
        }
        for(int i=0;i<initCount;i++){
            workThreads.add(new WorkThread());
            Thread thread = new Thread(new WorkThread());
            System.out.println("初始化线程总数" + (i + 1) + "------当前线程名称是:" + thread.getName());
            thread.start();
        }
    }

    //增加工作线程
    public static void addWorkThread(int count){
        if(count<0){
            return;
        }
        for(int i=0;i<count;i++){
            workThreads.add(new WorkThread());
            Thread thread = new Thread(new WorkThread());
            System.out.println("初始化线程总数" + (i + 1) + "------当前线程名称是:" + thread.getName());
            thread.start();
        }
    }

    //得到线程
    public static Runnable getRunnable(){
        return workThreads.remove(0);
    }

    //关闭线程
    public static void destory(){
        while(!workTask.isEmpty()){
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for(int i =0;i<workThreads.size();i++){
                WorkThread workThread = workThreads.get(i);
                workThread.isRunning = false;
                workThread = null;
        }
        workTask.clear();
    }

    //得到任务队列里面的个数
    public static int getWorkTask(){
        return workTask.size();
    }

    //得到已经执行的任务队列
    public static int getExecuteTaskNumber(){
        return executeTaskNumber;
    }

    //得到线程队列里面的个数
    public static int getThreadCount(){
        return workThreads.size();
    }

    //工作线程
    private static class WorkThread extends Thread{

        Runnable runnable = null;

        private boolean isRunning = true;

        @Override
        public void run() {
            while (isRunning) {
                synchronized (workTask) {
                    while (workTask.isEmpty()&&isRunning) {
                        try {
                            workTask.wait(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    if (!workTask.isEmpty()) {
                        runnable = workTask.remove(0);
                    }

                    if (runnable != null) {
                        runnable.run();
                    }
                    runnable = null;
                    executeTaskNumber++;
                }

            }
        }
    }

    //停止线程
    public static void  stopThread(){
        flag = false;
    }

}
ThreadPoolManagers类代码:
package com.mec.test;

import java.util.List;

public class ThreadPoolManagers implements ThreadPools {

    private int initCount = 5;

    private ThreadPoolManagers(){
        ThreadFactory.initWorkThread(initCount);
    }

    private ThreadPoolManagers(int count){
        ThreadFactory.addWorkThread(count);
    }

    public static ThreadPools getThreadPool(){
       return new ThreadPoolManagers();
    }

    public static ThreadPools getThreadPool(int count){
        return new ThreadPoolManagers(count);
    }

    @Override
    public void execute(Runnable task) {
        ThreadFactory.addWorkTask(task);
    }

    @Override
    public void execute(Runnable[] task) {
        ThreadFactory.addWorkTask(task);
    }

    @Override
    public void execute(List<Runnable> task) {
        ThreadFactory.addWorkTask(task);
    }

    @Override
    public int getExecuteTaskNumber() {
        return ThreadFactory.getExecuteTaskNumber();
    }

    @Override
    public int getWaitTaskNumber() {
        return ThreadFactory.getWorkTask();
    }

    @Override
    public int getWorkThreadNumber() {
        return ThreadFactory.getThreadCount();
    }

    @Override
    public void destory() {
        ThreadFactory.destory();
    }

    @Override
    public void stop() {
        ThreadFactory.stopThread();
    }

    @Override
    public String toString(){
        return "当前工作线程数:" + ThreadFactory.getThreadCount() +
                ", 已完成任务数:" + ThreadFactory.getExecuteTaskNumber() +
                ", 等待任务数量:" + ThreadFactory.getWorkTask();
    }

}
ThreadPools类代码:
package com.mec.test;

import java.util.List;

public interface ThreadPools {

    void execute(Runnable task);

    void execute(Runnable[] task);

    void execute(List<Runnable> task);

    //返回执行任务的个数
    int getExecuteTaskNumber();

    //返回任务队列的长度 即还没处理的任务个数
    int getWaitTaskNumber();

    //返回工作线程的个数
    int getWorkThreadNumber();

    //关闭线程池
    void destory();

    //停止线程
    void stop();
}

运行类代码:

package com.mec.test;


import java.util.ArrayList;
import java.util.List;

public class ThreadTest1 {
    public static void main(String[] args) {
        ThreadPools t = ThreadPoolManager.getThreadPool(6);

        List<Runnable> taskList = new ArrayList<Runnable>();

        for (int i = 0; i < 100; i++) {
            taskList.add(new Task());
        }
        t.execute(taskList);
        System.out.println(t);
        t.destory();//所有线程执行完才destory
        System.out.println(t);

    }

    //任务类

    static class Task implements Runnable {

        private static volatile int i = 1;

        @Override
        public void run() {
            System.out.println("当前处理的线程是:" + Thread.currentThread().getName() + " 执行任务" + (i++) + " 完成");
        }
    }
}

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值