多线程进阶(上)

目录

使用线程池的原因:

JDK的线程池的使用

ThreaPoolExecute的核心方法:

execute:

 submit:提交一个任务到线程池,线程池会派遣一个空闲的线程来执行该任务。

shutdown()/shutdownNow():销毁线程池 ,

 ThreadPoolExecutor子类的核心构造方法参数:

线程池的工作流程:

 固定大小线程池的源码

缓存线程池:同步阻塞队列,两个线程池同时获取和抛出一个任务。同步阻塞队列

 单一线程池:

延迟线程池:

采用锁的策略:

1,乐观锁:

2,悲观锁:

3,读写锁(ReentrantReadWriteLock实现读写锁)

 4,重量级锁和轻量级锁:

5,公平锁与非公平锁


使用线程池的原因:

当有多个线程频繁的创建销毁,就会浪费大量的时间,用来创建线程池,保存一定数量的线程,来回收线程,保证重复使用,以此来减少线程的创建与销毁的时间

JDK的线程池的使用

描述线程池的核心类:ThreadPoolExecutor(最常用的实现)

线程池的核心父接口:ExecuteService接口

这个类的构造方法,就是创建一个线程的所有核心参数,为了简化线程池的使用,jdk有新增加了几个类:

ThreaPoolExecute的核心方法:

execute:

 submit:提交一个任务到线程池,线程池会派遣一个空闲的线程来执行该任务。

 

shutdown()/shutdownNow():销毁线程池 ,

 

 

 

 

public static void main(String[] args) {
        //创建固定大小线程池
        ExecutorService pool1 = Executors.newFixedThreadPool(10);
        //创建定时线程池
//        ExecutorService pool2 = Executors.newScheduledThreadPool(10);
//        //创建可变大小线程池
//        ExecutorService pool3 = Executors.newCachedThreadPool();
//        //创建只有一个线程的线程池
//        ExecutorService pool4 = Executors.newSingleThreadExecutor();
        pool1.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        });
       

 线程的执行:除了定时线程池,其他的线程池都是调用submit方法,定时线程池也可以调用submit方法来执行任务。

        ExecutorService pool1 = Executors.newFixedThreadPool(10);
        //创建定时线程池
        ScheduledExecutorService pool2 = Executors.newScheduledThreadPool(10);
//        //创建可变大小线程池
//        ExecutorService pool3 = Executors.newCachedThreadPool();
//        //创建只有一个线程的线程池
//        ExecutorService pool4 = Executors.newSingleThreadExecutor();
        pool1.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        });
        pool1.shutdown();
        pool2.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("三秒后打印"+123);
            }
        },3000,TimeUnit.MILLISECONDS);
        pool2.shutdown();
    }

 ThreadPoolExecutor子类的核心构造方法参数:

线程池的工作流程:

当调用submit提交一个新任务时:

1,判断核心线程是否到达最大数量:

a,没有到达最大数量,创建一个新的线程,放到核心线程中

b,到达最大数量 ,执行2

2,判断工作队列是否已满

a,blockingQueue未满,直接将任务入队列

b,若队列已满,执行3

3,判断当前线程数量,是否达到最大线程数

a,未达到,创建临时线程,执行任务

b,达到最大线程数量,执行4

4,拒绝策略:

 固定大小线程池的源码

缓存线程池:同步阻塞队列,两个线程池同时获取和抛出一个任务。同步阻塞队列

 

 单一线程池:

延迟线程池:

 

 阿里编码规范,自定义线程数量大小,避免使用系统线程池。

采用锁的策略:

1,乐观锁:

每次读写数据,认为线程不会发生阻塞,一般来说,一般只有在更新数据时,判断是否冲突,若没有冲突,直接更新,若冲突(多线程同时更新数据),解决冲突。

2,悲观锁:

认为每次读写数据,都会冲突,每次在数据读写时,都会上锁,保证每次只有一个线程读写数据,确保数据绝对安全。

乐观锁的实现:采用版本号机制实现乐观锁(CAS)

 一般锁的实现:采用乐观锁与悲观锁并用的策略

3,读写锁(ReentrantReadWriteLock实现读写锁)

多线程在读操作时,不会冲突,写操作时,才会冲突。

并发读锁,并发

并发写锁:互斥,串行

读写并行:先写在读,串行。

 4,重量级锁和轻量级锁:

轻量级锁:由cpu调度,自旋方式

重量级锁:需要os调用的参与,当获取锁失败,进入阻塞,从用户态切换到核心态。

轻量级锁的实现:采用自旋方式

自旋锁:当获取不到锁,就一直在循环,不让出cpu,不阻塞,不从用户态切换到核心态,如果一旦对象被释放,就立即对对象进行加锁。

5,公平锁与非公平锁

公平锁:先来先服务的线程调度算法

非公平锁:锁被释放,所有线程同时竞争。synchronized为非公平锁

锁的升级:

偏向锁  ——> 轻量级锁 ——> 重量级锁。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值