美文网首页
30 线程池底层原理

30 线程池底层原理

作者: 滔滔逐浪 | 来源:发表于2020-07-29 09:09 被阅读0次

为什么要使用线程池:
如果频繁的创建线程的情况下,非常的消耗cpu资源,重复放从就绪到运行状态调度,效率非常低。
所以采用线程池直接实现反复复用,创建好一个线程后,不会立马销毁掉,而是一直复用。从而直接从运行状态调度,可以提高效率。

为什么使用线程池可以提高效率:无需cpu调度切换,直接运行。
线程池的优缺点:
1,效率比较高
2,统一管理我们的线程
3,提高线程复用。
缺点:
非常消耗cpu资源:

线程池里面: 核心线程数,最大线程数。超时时间

线程池的作用

1.降低资源消耗:通过池化技术重复利用已创建的线程,降低线程创建和销毁造成的损耗。
2.提高响应速度:任务到达时,无需等待线程创建即可立即执行。
3.提高线程的可管理性:线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。
4.提供更多更强大的功能:线程池具备可拓展性,允许开发人员向其中增加更多的功能。比如延时定时线程池ScheduledThreadPoolExecutor,就允许任务延期执行或定期执行

线程池的创建方式:
Executors.newCachedThreadPool(); 可缓存线程池
Executors.newFixedThreadPool();可定长度
Executors.newScheduledThreadPool() ; 可定时
Executors.newSingleThreadExecutor(); 单例
底层都是基于ThreadPoolExecutor构造函数封装

简单手写线程池:
可定长线程池:

package com.taotao.metithread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 *@author tom
 *Date  2020/7/29 0029 8:03
 *创建线程池
 */
public class Test040 {
    public static void main(String[] args) {
        //底层只会创建2个线程复用
        //可以定长线程池
        ExecutorService executorService= Executors.newFixedThreadPool(2);
        for (int i = 0; i <10 ; i++) {
            int fini=i;
            executorService.execute(()->
                    System.out.println(Thread.currentThread().getName()+":"+fini));
        }


    }


}

 public static ExecutorService newCachedThreadPool() {
//核心线程数,最大线程数,单位(分、秒),队列
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }


    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

1,newFixedThreadPool 采用的是无界队列 LinkedBlockingQueue

阻塞队列

1.ArrayBlockingQueue:
有界队列,基于数组结构,按照队列FIFO原则对元素排序;
2.LinkedBlockingQueue:
无界队列,基于链表结构,按照队列FIFO原则对元素排序,Executors.newFixedThreadPool()使用了这个队列; 无界默认是Integer.MAX_VALUE,有界则是 可以自己定义
3.SynchronousQueue:
同步队列,该队列不存储元素,每个插入操作必须等待另一个线程调用移除操作,否则插入操作会一直被阻塞,Executors.newCachedThreadPool()使用了这个队列;
4.PriorityBlockingQueue:
优先级队列,具有优先级的无限阻塞队列。

有界无界的区分: 是否设置初始值。
LinkedBlockingDeque



package com.taotao.metithread;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

/**
 *@author tom
 *Date  2020/7/29 0029 8:38
 *阻塞与非阻塞
 */
public class Test042 {
    public static void main(String[] args) throws InterruptedException {
        LinkedBlockingDeque<String> strings=new LinkedBlockingDeque<>(3);
        strings.offer("mayikt");
        strings.offer("meite");
        strings.offer("wwss");
        strings.offer("23");
        boolean xiaowie=strings.offer("xiaowie",3,TimeUnit.SECONDS);
        System.out.println(xiaowie);
//        System.out.println(strings.peek());
//        System.out.println(strings.peek());
//        System.out.println(strings.peek());
//        System.out.println(strings.peek());
        System.out.println(strings.poll());
        System.out.println(strings.poll());
        System.out.println(strings.poll());
        System.out.println(strings.poll(3, TimeUnit.SECONDS));
        //poll取出成功的话会将元素从队列删除
       //peek 获取元素不删除


    }
}

image.png
package com.taotao.metithread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

/**
 *@author tom
 *Date  2020/7/29 0029 9:21
 *手写线程池
 */
public class MayijtExecutor {
    //存放我们提交任务的线程
    private BlockingQueue<Runnable> runnables;
    //一直运行的线程,核心线程:
    private List<TaskThread> taskThreads;

    public MayijtExecutor(int codeThreads, int queueSize) {
        taskThreads = new ArrayList<TaskThread>();
        runnables = new LinkedBlockingDeque(queueSize);

        for (int i = 0; i < codeThreads; i++) {
            TaskThread taskThread = new TaskThread();
            taskThread.start();
            taskThreads.add(taskThread);
        }
    }

    class TaskThread extends Thread {
        @Override
        public void run() {
            //停掉线程池
            while (runnables.size() > 0 || true) {
                Runnable runnable = runnables.poll();
                if (runnable != null) {
                    runnable.run();
                }
            }
        }
    }

    public boolean executor(Runnable runnable) throws InterruptedException {
        runnables.offer(runnable, 2, TimeUnit.SECONDS);
        return false;
    }

    public static void main(String[] args) throws InterruptedException {
        MayijtExecutor myExecutor = new MayijtExecutor(2, 2);
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            boolean executor = myExecutor.executor(() -> {
                System.out.println(Thread.currentThread().getName() + "," + finalI);
            });


        }
    }
}

相关文章

  • 一文搞懂Java线程池原理之ThreadPoolExecutor

    在工作中,我们经常使用线程池,但是你真的了解线程池的原理吗?同时,线程池工作原理和底层实现原理也是面试经常问的考题...

  • 线程池底层原理和拒绝策略

    线程池底层原理 用一个银行网点说明底层原理线程池相当于一个银行网点,假设网点有五个柜台(maximumPoolSi...

  • 面试题2019年7月

    线程池原理 参考:Java 线程池原理分析 线程池工作原理:1、线程数量小于 corePoolSize,直接创建新...

  • 多线程与GCD执行原理

    多线程与GCD执行原理 GCD 含义 可以生成必要的线程并计划执行任务 实现原理 GCD有一个底层线程池,这个池中...

  • 浅谈GCD

    GCD实现原理: GCD有一个底层线程池,这个池中存放的是一个个的线程。之所以称为“池”,很容易理解出这个“池”中...

  • 源码分析AsyncTask的工作原理

    一、AsyncTask原理介绍 AsyncTask的实现原理 = 线程池+ Handler 其中:线程池用于线程调...

  • iOS大厂面试点(绝对高频)

    技术类: 1. 性能优化 2. 底层原理 Runtime - Runloop 线程 自动释放池什么时候释放 A...

  • Spring线程池ThreadPoolTaskExecutor学

    ThreadPoolTaskExecutor线程是Spring的线程池,其底层是依据JDK线程池ThreadPoo...

  • 427,GCD执行原理(面试点:GCD有一个底层线程池,注意:开

    一,GCD执行原理 1.GCD有一个底层线程池,这个池中存放的是一个个的线程。之所以称为“池”,很容易理解出这个“...

  • Java线程池进阶

    线程池是日常开发中常用的技术,使用也非常简单,不过想使用好线程池也不是件容易的事,开发者需要不断探索底层的实现原理...

网友评论

      本文标题:30 线程池底层原理

      本文链接:https://www.haomeiwen.com/subject/rztwlktx.html