一篇让你掌握线程和线程池,还解决了线程安全问题,确定不看看?

1.线程和进程

进程

进程是资源分配的基本单位,是程序执行时的一个实例,程序运行时系统就会创建一个进程,也就是说你的电脑每开启一个程序,就产生一个进程,然后这个进程会放入就绪队列,进程调度器选中时会进行分配cpu的时间,程序进行运行

线程

操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。

2.创建线程的方式

A-继承Thread类

先让一个类进行继承Thread类,在里面进行run方法的编写,在进行新建该类进行start的启动

 B-实现Runnable接口

先进行一个类进行实现接口runnable,复写里面的方法fun

在进行新建一个实现类,在把这个实现类给放在新建的thread类进行start方法进行启动

C-实现Callable接口

 创建一个类进行实现Callable接口,覆写call方法,把新建的类callable类放到新建的FutureTask类里面,再把callable放到新建的Thread类里面在进行start进行启动

D-线程池-(这里是提供的固定的长度的线程)

private ExecutorService executorService = Executors.newFixedThreadPool(5);

    public static void main(String[] args) {
        executorService.execute(()->{
            System.out.println("线程池创建的线程");
        });
    }

3.线程池的详细介绍

3.1线程池的作用

A-控制并发数量:线程并发数量过多,抢占系统资源从而导致阻塞,线程池可以限制线程的数量

B-线程的复用:创建/销毁线程伴随着系统开销。过于频繁的创建/销毁线程,会很大程度上影响处理效果和速度

C-管理线程的生命周期:对线程进行一些简单的管理,创建,销毁等

3.2线程池的执行流程

核心线程>=等待队列>=非核心线程>=拒绝策略

核心线程:一个线程池里面的核心主要的线程核心数

等待队列:当任务来了,但是线程池里面的核心线程都在进行工作,那就把这个任务放到等待队列里面进行排队,等待核心线程空出去执行任务

非核心线程:当等待队列里面的任务过多,就会开启非核心线程去处理任务,但是非核心线程数和核心线程数之和不能超过最大线程数

拒接策略:当非核心线程数和核心线程数之和超过最大线程数,1.线程丢弃正在处理的任务去处理队列里面的任务,2.交给main主线程处理,3.不处理

注意:

1.如果有空闲的线程直接进行使用,没有空闲的线程并线程的数量没有达到corePoolSize,则新建一个线程(核心线程)去执行任务

2.当线程的数量达到了corePoolSize,就把这个任务放到队列去,通过getTask方法进行去拿到队列里面的任务,如果队列里面没有任务,getTaask将会进入阻塞状态,直到获取到任务,期间不会对cup进行资源的消耗。

3.3线程池的七大核心参数

  1. corePoolSize:核心线程数。
  2. maximumPoolSize:最大线程数。
  3. keepAliveTime:空闲线程存活时间,当非线程空闲的时间达到这个时间时会进行销毁
  4. TimeUnit:空闲时间单位
  5. BlockingQueue:线程池任务队列。
  6. ThreadFactory:创建线程的工厂
  7. RejectedExecutionHandler:拒绝策略  AbortPolicy丢弃任务并跑出异常,DiscardPolicy丢弃任务但是我不告诉你,DiscardOldestPolicy我会把队列里面最前面的任务丢掉,CallerRunsPolicy 叫我老大main主线程来处理

3.4jdk自带的线程池

1.CachedThreadPool 可缓存的

2.FixedThreadPool 固定长度的

3.SingleThreadPool  单一的

4.ScheduledThreadPool 可调度的

四大线程的对比图

在这里插入图片描述

 自带的线程池都可通过Executor来进行创建

3.5 DIY线程池

为什么有了自带的线程池还有进行自己DIY线程池?

阿里不推荐使用Executors创建线程池

1.FixedThreadPool和SingleThreadExecutor => 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而引起OOM异常


2.CachedThreadPool => 允许创建的线程数为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM
 

public class MyThreadFactory {

    public static void main(String[] args) {

        new ThreadPoolExecutor(4,//核心数量4个
                9,//最大线程不超过9个
                2L,//2分钟去销毁空闲的非核心的线程
                TimeUnit.MINUTES,//单位分
                new ArrayBlockingQueue<Runnable>(9),//等待队列 最大等9个
                new ThreadPoolExecutor.AbortPolicy()//任务满了我就丢了再给你抛异常
        );
    }

}

4 线程安全-锁

1.线程安全问题

就是 多线程环境中 , 且存在数据共享 , 一个线程访问的共享 数据被其他线程修改了, 那么就发生了线程安全问题 , 整个访问过程中 , 无一共享的数据被其他线程修改了 就是线程安全的
程序中如果使用成员变量, 且对成员变量进行数据修改 , 就存在数据共享问题, 也就是线程安全问题
 

2.锁

锁是来进行解决线程安全的问题,一般分为悲观和乐观锁,

悲观锁:顾名思义,就是认为每次拿数据都会出现问题,那就在那数据之前进行锁上,下一个拿数据等锁释放之后在进行拿数据,比如synchronized锁

乐观锁:认为每次拿数据都不会出现问题,所以当拿数据出现问题之后才进行处理上锁,基于cas锁

3.第一种锁sychronized锁

sychronized锁是一个java的关键字,是jvm给我们进行实现了的,它的主要的实现的一个原理是jvm内置锁有一个对象头监视器对对象进行监视,说这个对象有锁了,那它的对象头上就会有一个标记,那其他的线程就不能进行操作

4.关于sychronized锁的膨胀机制或升级机制

A-先是偏向锁就是说这个有一个线程进行操作,下次这个线程又来了就还是给这个线程进行操作

B-来了一个线程多个线程那就进行轻量级锁,这个后来的锁进行一个自旋,进行不断判断上一个线程是否完成了操作

C-重量级锁,这个是为了避免忙等的,当这个线程进行自旋10次就进行不在等进行线程的放回

5.第二种锁lock

lock是一个接口,jdk提供的一个接口是juc并发库里面的,这个是要我们进行手动释放锁的(就是unlock),而sychronized是不需要的

6.第三把锁 原子类(其实不太算是锁,但可以解决线程安全问题)

原子类是juc下面的一个包atomic类,它里面是我们封装了不同类型封装的原子类,我们直接拿来用即可,

所以我的大致解决线程问题的思路就是:要不你就加锁,那线程一个一个排位来进行操作。要不就解决原子性(只有一个)

7.关于出现的CAS和ABA问题

CAS:对比并更新

大致意思是:有三大东西,U是这个变量的值是否是一致的,A是预期值 ,B更新值 

先进行对比,看这个A和U的值是否是一致的,只有是满足时才进行更新内存的值为B值

ABA:就是有一个变量的值是10的时候,A进行添加操作进行+1的操作,而B线程来了之后进行-1的操作这样下来这个值还是10,当C来进行操作的时候,它吧这个10拿出来不是之前A操作的时候10那个值了,所以就出现了ABA的问题

它的解决方案是进行添加一个版本号进行区分,比如 ElasticSearch

关于详细的CAS问题可参考下面文章

https://blog.csdn.net/bjweimengshu/article/details/78949435?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165880780516782246423613%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=165880780516782246423613&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-78949435-null-null.185^v2^control&utm_term=CAS&spm=1018.2226.3001.4450

欢迎进行学习交流,不足之处请指出,喜欢麻烦点赞+收藏,谢谢各位大佬了

猜你喜欢

转载自blog.csdn.net/m0_67601895/article/details/125969080
今日推荐