资讯 小学 初中 高中 语言 会计职称 学历提升 法考 计算机考试 医护考试 建工考试 教育百科
栏目分类:
子分类:
返回
空麓网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
空麓网 > 计算机考试 > 软件开发 > 后端开发 > Java

多线程之线程池

Java 更新时间: 发布时间: 计算机考试归档 最新发布

多线程之线程池

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录
  • 前言
  • 一、什么是线程池
  • 二.为什么要有线程池
      • 引入:
      • 为什么从池子里取,比创建线程速度要快
      • 什么是用户态,什么是内核态
      • 最终结论:
  • 三.标准库中的线程池
  • 四.自己实现一个线程池
    • 生产者消费者模型策略:
    • 代码演示:
    • 完整代码:
  • 五.线程池的拒绝策略 (超级重点):
    • 引入
    • 标准库中拒绝策略(对于threadpoolExecutr的理解)
    • 延伸的问题:
      • 实际开发中线程池数目如何确定:


前言

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、什么是线程池

类似String字符串常量池,mysql jdbc数据库链接池
搞一个池子,创建好许多线程,当需要执行任务的时候,不需要在重新创建线程,而是直接从池子里取一个现成的线程,直接使用,用完了也不释放,而是直接放回线程池里

二.为什么要有线程池 引入:

线程诞生的目的是进程太重量了,创建进程或销毁进程,都是比较低效(内存资源的申请和释放),线程就是共享了内存资源,新的线程复用之前的资源,不必重新申请,但是如果线程创建的速率进一步频繁,此时线程创建开销仍然不能忽略此时可以采用线程池来优化速度

为什么从池子里取,比创建线程速度要快

实际上,创建线程也需要申请资源(很少),创建线程,也是要在操作系统内核中完成,涉及到用户态->内核态切换操作,也存在一定的开销

什么是用户态,什么是内核态


应用程序发起的一个创建线程的行为,本质上是pcb,是内核中的数据结构,
应用程序需要通过系统调用,进入到操作系统内核中执行,
内核完成pcb的创建,把pcb加入到调度队列,再返回给应用程序

从线程池取线程,把线程放回线程池,这是纯用户态的逻辑
从系统这里创建线程,是用户态+内核态共同完成的逻辑

最终结论:

使用线程池是纯用户态的操作,要比创建线程(经历内核态的操作)要快**

三.标准库中的线程池
  ExecutorService pool= Executors.newCachedThreadPool();
        pool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("这是任务");
            }
        });

0.标准库中线程池构造方法的参数

1.如果直接采取构造方法创建线程池(参数太多)写起来麻烦,为了简化构造,标准库提供了一系列工厂方法

2.此处创建线程池没有显示new,而是通过executor类的静态方法newCachedThreadpool来完成

3.工厂模式的好处:
绕开构造方法的局限(参数太多),而且构造方法有时候不能重载(返回值,参数列表都相同)

我们可以使用普通方法代替构造方法(普通方法方法名可以随便取来重载),在普通方法创建point对象,通过其他手段设置

 public static Point makePointByXY(double x,double y){
        Point p=new Point();
        p.setR(x);
        p.setA(y);
        return p;
    }
    private void setA(double a){

    }
    private void setR(double r){

    }
   

线程池的使用采取submit方法,把任务提交到线程池中即可,线程池里面有线程完成这里的任务

四.自己实现一个线程池

一个线程池可以同时提交n个任务,对应的线程池就有m个线程来负责完成这n个任务

生产者消费者模型策略:

先搞一个阻塞队列,每个被提交的任务都被放到阻塞队列当中,
搞m个线程来取队列元素,如果队列空了,m个线程自然阻塞等待,
队列不为空,每个线程都取任务,执行任务,再取下一个任务,直到队列为空

代码演示:
  public MyThreadPool(int m){
        //在构造方法中,创建出m个线程,负责完成工作
        for (int i = 0; i 
            Thread t=new Thread(()->{
                while(true){
                    try {
                        Runnable runnable=queue.take();
                        runnable.run();
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }
            });
            t.start();
        }
    }

创建m个线程,让线程持续的扫描队列,执行其中方法

完整代码:
package Threading;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

//演示自己创建的线程池
class MyThreadPool{
    private BlockingQueue queue=new LinkedBlockingDeque<>();

    public void submit(Runnable runnable) throws InterruptedException{
        queue.put(runnable);
    }

    public MyThreadPool(int m){
        //在构造方法中,创建出m个线程,负责完成工作
        for (int i = 0; i 
            Thread t=new Thread(()->{
                while(true){
                    try {
                        Runnable runnable=queue.take();
                        runnable.run();
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }
            });
            t.start();
        }
    }
}
public class demo28 {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPool pool=new MyThreadPool(10);
        for (int i = 0; i <1000 ; i++) {
            int taskId=i;
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("执行当前任务: "+taskId+"当前线程: "+Thread.currentThread().getName());
                }
            });
        }
    }

}
五.线程池的拒绝策略 (超级重点): 引入

线程池的拒绝策略,线程池的任务队列已经满了(工作线程已经忙不过来了)
当前任务数>workqueue.size()+maximumpoolsize
如果又有人往里添加新的任务,问题:
这个策略对于高并发服务器,也是非常有意义的

标准库中拒绝策略(对于threadpoolExecutr的理解)


AbortPolicy 直接丢弃任务,抛出异常,必须处理好异常,否则打断当前执行流程默认策略
CallerrunsPolicy 只用调用者所在的线程来处理任务
discradoldesrPolict 丢弃等待队列中最旧的任务,并执行当前任务
DiscardPolicy 直接丢器,啥事没有

延伸的问题: 实际开发中线程池数目如何确定:

实践是检验真理的唯一标准
针对你的程序进行性能测试,分别给线程设置成不同的数目,分别记录每种情况下,你的程序一些核心性能制表和系统负载情况,选一个最合适的

转载请注明:文章转载自 http://www.konglu.com/
本文地址:http://www.konglu.com/it/1042267.html
免责声明:

我们致力于保护作者版权,注重分享,被刊用文章【多线程之线程池】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理,本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意,谢谢!

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2023 成都空麓科技有限公司

ICP备案号:蜀ICP备2023000828号-2