线程池

线程池

池化技术

程序运行,本质:占用系统的资源!优化资源的使用=》池化技术

池化技术:事先准备好一些资源,有人用,就来拿,用完返回池

线程池的好处:

1、降低资源的消耗

2、提供响应的速度

3、方便管理

线程服用、可以控制最大并发数、管理线程

线程池:三大方法、7大参数、4种拒绝策略

三大方法

//使用线程池要用线程池创建线程
public class Demo1 {
    public static void main(String[] args) {
//        ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程
//        ExecutorService threadPool = Executors.newFixedThreadPool(5);//创建一个固定的线程池大小
        ExecutorService threadPool = Executors.newCachedThreadPool();//可伸缩的

        try {
            for (int i = 0; i < 100; i++) {
                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName() + "ok");
                });

            }
            //线程池用完需要结束线程池
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            threadPool.shutdown();
        }

    }
}

最好不要通过Executors创建线程池,而是通过ThreadPoolExecutor的方式创建,避免内存泄漏

最大 线程为21亿线程

@Native public static final int   MAX_VALUE = 0x7fffffff;

7大参数

public ThreadPoolExecutor(int corePoolSize, //核心线程池大小
                          int maximumPoolSize,//最大核心线程池大小
                          long keepAliveTime,//超时时间(没有人调用释放)
                          TimeUnit unit,//超时单位
                          BlockingQueue<Runnable> workQueue,//阻塞队列
                          ThreadFactory threadFactory) {//线程工厂,创建线程用的,一般不用动
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         threadFactory, defaultHandler);//defaultHandler拒绝策略
}

4种拒绝策略

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WNZuNrGO-1617319742111)(C:\Users\zyq zt\AppData\Roaming\Typora\typora-user-images\image-20210401215516907.png)]

public class Demo2 {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,
                5,
                3,
                TimeUnit.SECONDS, new LinkedBlockingQueue<>(4),
//                new ThreadPoolExecutor.CallerRunsPolicy(),
//                new ThreadPoolExecutor.DiscardOldestPolicy(),
                new ThreadPoolExecutor.DiscardPolicy());
        //默认AbortPolicy拒绝策略 超过队列抛出异常容量为::最大核心线程池大小+阻塞队列数
        //CallerRunsPolicy 哪里来的回哪里去
        //ThreadPoolExecutor.DiscardPolicy() 队列满了不抛出异常
        //ThreadPoolExecutor.DiscardOldestPolicy() 队列满了抛弃最老的

        try {
            for (int i = 1; i <= 10; i++) {
                threadPoolExecutor.execute(()->{
                    System.out.println(Thread.currentThread().getName()+" ok");
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            threadPoolExecutor.shutdown();
        }
    }
}

最大线程如何定义

(调优方式)

CPU密集型:几核就是可以定义多少个线程

IO密集型:判断你程序十分耗IO的线程,如果是15个,设置30个

四大函数式接口

lambda表达式

链式编程

函数式接口

Stream流计算

函数式接口

只有一个函数的接口,简化编程模型,在新版本的框架底层大量运用

        List list = new ArrayList();
	    list.forEach();//函数式接口
public static void main(String[] args) {
    //    Function<T,R> //传入参数T,返回参数R
    
    Function<String,Integer> function = (a) -> {return 2;};
    System.out.println(function.apply("1"));

    //断定型接口
    Predicate<String> predicate = (str)->{ return str.isEmpty();};
    System.out.println(predicate.test("aaa"));

    //

}

    public static void main(String[] args) {
        //Consumer只有输入没有返回
        Consumer<String> consumer = (str) -> System.out.println(str);
        consumer.accept("aaa");

        //Supplier值返回不输入
        Supplier<String> supplier = () -> {return "aaa1";};
        System.out.println(supplier.get());
    }

流式计算

public class Test {
    //链式编程
    public static void main(String[] args) {
        User u1 = new User(1,"zzz",21);
        User u2 = new User(2,"www",22);
        User u3 = new User(3,"yyy",23);
        User u4 = new User(4,"ddd",24);
        User u5 = new User(5,"sss",25);
        List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
        Arrays.asList(u1,u2,u3,u4,u5).stream()
                .filter(p -> p.getId()%2==0).forEach(System.out::println);

        list.stream().map( u -> u.getName().toUpperCase(Locale.ROOT)).forEach(System.out::println);
    }
}

ForkJoin

并行执行任务,提高效率

分而治之

特点:工作窃取====》原理双端队列

异步回调、

//异步调用ajax
//异步执行
//成功回调
public class Demo01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //

        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "runAsync=>void");
        });
        System.out.println("==============");
        completableFuture.get(); //获取阻塞执行结果


        //有返回值的异步回调
        CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(()->{
            return 11;
        });
        System.out.println(completableFuture1.whenComplete((t, u) -> {
            System.out.println(t);//正常返回结果
            System.out.println(u);//错误信息
        }).exceptionally((t) -> {
            System.out.println(t.getMessage());
            return 1;
        }).get());
    }
}

JMM

Volatiler:是java虚拟机提供轻量级的同步机制

保证可见性:怎么保证可见性—需要了解JMM

不保证原子性

禁止指令重排

关于JMM的一些同步的约定:

  • 线程解锁前,必须把共享变量立刻刷新回主存
  • 线程加锁前,必须读取主存中的最新值到工作内存中
  • 加锁和解锁是同一把锁

线程分为 工作内存、主内存

8种操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-axmb9B9N-1617319742113)(C:\Users\zyq zt\AppData\Roaming\Typora\typora-user-images\image-20210402071025816.png)]

(1)lock(锁定):作用于 主内存的变量,把一个变量标记为一条线程独占状态

(2)unlock(解锁):作用于 主内存的变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定

(3)read(读取):作用于 主内存的变量,把一个变量值从主内存传输到线程的 工作内存中,以便随后的load动作使用

(4)load(载入):作用于 工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中

(5)use(使用):作用于 工作内存的变量,把工作内存中的一个变量值传递给执行引擎

(6)assign(赋值):作用于 工作内存的变量,它把一个从执行引擎接收到的值赋给工作内存的变量

(7)store(存储):作用于 工作内存的变量,把工作内存中的一个变量的值传送到 主内存中,以便随后的write的操作

(8)write(写入):作用于 工作内存的变量,它把store操作从工作内存中的一个变量的值传送到 主内存的变量中

保证可见性

public class JMMDemo {
    //不加volatile会死循环
    //volatile可以保证可见性
    private volatile static int num = 0; 
    public static void main(String[] args) {

        new Thread(()->{
            while (num ==0){ //线程不知道内存种num值已经被修改了,会一直循环

            }
        }).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        }catch (InterruptedException e){

        }
        num = 1;
        System.out.println(num);
    }
}

不保证原子性

线程A执行任务的时候,不能被打扰,要么同时成功,要么同时失败

public class VDemo2 {
    //volatile 不保证原子性 可通过lock和sychronized保证原子性
    //不用锁如果保证原子性 num++不保证原子性
    //可以使用原子类,处理原子问题(效率比锁高)
    private volatile static AtomicInteger num = new AtomicInteger();
    public static void add(){
//        num ++;
        num.getAndIncrement();
    }

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            new Thread(()->{
                for (int j = 0; j < 1000; j++) {
                    add();
                }
            }).start();

        }
        while (Thread.activeCount()>2) {
            Thread.yield();
        }
        System.out.println(Thread.currentThread().getName() + "" + num);
    }

}

{
new Thread(()->{
for (int j = 0; j < 1000; j++) {
add();
}
}).start();

    }
    while (Thread.activeCount()>2) {
        Thread.yield();
    }
    System.out.println(Thread.currentThread().getName() + "" + num);
}

}


num.getAndIncrement();这些类的底层都是直接和操作系统挂钩,在内存中修改值!Unsafe类是一个很特殊的存在!

热门文章

暂无图片
编程学习 ·

那些年让我们目瞪口呆的bug

程序员一生与bug奋战&#xff0c;可谓是杀敌无数&#xff0c;见怪不怪了&#xff01;在某知识社交平台中&#xff0c;一个“有哪些让程序员目瞪口呆的bug”的话题引来了6700多万的阅读&#xff0c;可见程序员们对一个话题的敏感度有多高。 1、麻省理工“只能发500英里的邮件” …
暂无图片
编程学习 ·

redis的下载与安装

下载redis wget http://download.redis.io/releases/redis-5.0.0.tar.gz解压redis tar -zxvf redis-5.0.0.tar.gz编译 make安装 make install快链方便进入redis ln -s redis-5.0.0 redis
暂无图片
编程学习 ·

《大话数据结构》第三章学习笔记--线性表(一)

线性表的定义 线性表&#xff1a;零个或多个数据元素的有限序列。 线性表元素的个数n定义为线性表的长度。n为0时&#xff0c;为空表。 在比较复杂的线性表中&#xff0c;一个数据元素可以由若干个数据项组成。 线性表的存储结构 顺序存储结构 可以用C语言中的一维数组来…
暂无图片
编程学习 ·

对象的扩展

文章目录对象的扩展属性的简洁表示法属性名表达式方法的name属性属性的可枚举性和遍历可枚举性属性的遍历super关键字对象的扩展运算符解构赋值扩展运算符AggregateError错误对象对象的扩展 属性的简洁表示法 const foo bar; const baz {foo}; baz // {foo: "bar"…
暂无图片
编程学习 ·

让程序员最头疼的5种编程语言

世界上的编程语言&#xff0c;按照其应用领域&#xff0c;可以粗略地分成三类。 有的语言是多面手&#xff0c;在很多不同的领域都能派上用场。大家学过的编程语言很多都属于这一类&#xff0c;比如说 C&#xff0c;Java&#xff0c; Python。 有的语言专注于某一特定的领域&…
暂无图片
编程学习 ·

写论文注意事项

参考链接 给研究生修改了一篇论文后&#xff0c;该985博导几近崩溃…… 重点分析 摘要与结论几乎重合 这一条是我见过研究生论文中最常出现的事情&#xff0c;很多情况下&#xff0c;他们论文中摘要部分与结论部分重复率超过70%。对于摘要而言&#xff0c;首先要用一小句话引…
暂无图片
编程学习 ·

安卓 串口开发

上图&#xff1a; 上码&#xff1a; 在APP grable添加 // 串口 需要配合在项目build.gradle中的repositories添加 maven {url "https://jitpack.io" }implementation com.github.licheedev.Android-SerialPort-API:serialport:1.0.1implementation com.jakewhart…
暂无图片
编程学习 ·

2021-2027年中国铪市场调研与发展趋势分析报告

2021-2027年中国铪市场调研与发展趋势分析报告 本报告研究中国市场铪的生产、消费及进出口情况&#xff0c;重点关注在中国市场扮演重要角色的全球及本土铪生产商&#xff0c;呈现这些厂商在中国市场的铪销量、收入、价格、毛利率、市场份额等关键指标。此外&#xff0c;针对…
暂无图片
编程学习 ·

Aggressive cows题目翻译

描述&#xff1a; Farmer John has built a new long barn, with N (2 < N < 100,000) stalls.&#xff08;John农民已经新建了一个长畜棚带有N&#xff08;2<N<100000&#xff09;个牛棚&#xff09; The stalls are located along a straight line at positions…
暂无图片
编程学习 ·

剖析组建PMO的6个大坑︱PMO深度实践

随着事业环境因素的不断纷繁演进&#xff0c;项目时代正在悄悄来临。设立项目经理转岗、要求PMP等项目管理证书已是基操&#xff0c;越来越多的组织开始组建PMO团队&#xff0c;大有曾经公司纷纷建造中台的气质&#xff08;当然两者的本质并不相同&#xff0c;只是说明这个趋势…
暂无图片
编程学习 ·

Flowable入门系列文章118 - 进程实例 07

1、获取流程实例的变量 GET运行时/进程实例/ {processInstanceId} /变量/ {变量名} 表1.获取流程实例的变量 - URL参数 参数需要值描述processInstanceId是串将流程实例的id添加到变量中。变量名是串要获取的变量的名称。 表2.获取流程实例的变量 - 响应代码 响应码描述200指…
暂无图片
编程学习 ·

微信每天自动给女[男]朋友发早安和土味情话

微信通知&#xff0c;每天给女朋友发早安、情话、诗句、天气信息等~ 前言 之前逛GitHub的时候发现了一个自动签到的小工具&#xff0c;b站、掘金等都可以&#xff0c;我看了下源码发现也是很简洁&#xff0c;也尝试用了一下&#xff0c;配置也都很简单&#xff0c;主要是他有一…
暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法&#xff0c;在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较&#xff0c;从而确定目标数是在中间数的左边还是右边&#xff0c;将查…
暂无图片
编程学习 ·

项目经理,你有什么优势吗?

大侠被一个问题问住了&#xff1a;你和别人比&#xff0c;你的优势是什么呢? 大侠听到这个问题后&#xff0c;脱口而出道&#xff1a;“项目管理能力和经验啊。” 听者抬头看了一下大侠&#xff0c;显然听者对大侠的这个回答不是很满意&#xff0c;但也没有继续追问。 大侠回家…
暂无图片
编程学习 ·

nginx的负载均衡和故障转移

#注&#xff1a;proxy_temp_path和proxy_cache_path指定的路径必须在同一分区 proxy_temp_path /data0/proxy_temp_dir; #设置Web缓存区名称为cache_one&#xff0c;内存缓存空间大小为200MB&#xff0c;1天没有被访问的内容自动清除&#xff0c;硬盘缓存空间大小为30GB。 pro…
暂无图片
编程学习 ·

业务逻辑漏洞

身份认证安全 绕过身份认证的几种方法 暴力破解 测试方法∶在没有验证码限制或者一次验证码可以多次使用的地方&#xff0c;可以分为以下几种情况︰ (1)爆破用户名。当输入的用户名不存在时&#xff0c;会显示请输入正确用户名&#xff0c;或者用户名不存在 (2)已知用户名。…