线程相关

1.线程相关基本知识

  1. 进程是计算机进行资源分配的最小单位
  2. 线程是计算机进行任务调度的最小单位
  3. 一个进程至少有一个线程
  4. 一个核同一个时刻只能执行一个线程
  5. 多道编程的意义:
意义是为了提高cpu的利用率
原理是线程在执行任务的过程中有一部分时间的确实在计算,但另一部分时间并没有占用cpu,而是与硬件进行IO交互
  1. Callable接口与Runnable接口的区别.
1.实现Runnable接口的线程执行完没有返回值,实现Callable接口的线程有返回值,可在泛型中指定返回值类型
2.实现Runnable接口的线程可以通过Thread启动,也可以通过线程池启动,实现Callable接口的线程只能通过线程池来执行
3.实现Runnable借口就的线程没有容错机制,必须自己处理,实现Callable接口的线程可以抛出异常全局处理(Spring aop处理)
  1. new Thread().start 开启一个线程

2.BIO与NIO与AIO

同步式阻塞式IO BIO
同步式非阻塞IO NIO(三大组件Buffer,Channel,Selector)
异步式非阻塞式IO AIO jdk1.8

3.NIO与BIO的优缺点

1.BIO缺点:

1.阻塞
2.一个连接过来服务器需要开一个线程专门吃
若连接不发生任务操作 线程依旧被占用消耗服务器资源
3.无法实现定点操作

2.NIO相对BIO的有点

1.非阻塞效率高
2.一个服务器线程可处理多个客服端连接的请求
3.即使建立了连接 没有读写事件 服务器线程并不处理
4.数据可以双向传输(通道实现)
5.可以实现定点操作(缓冲区存储数据)

4.基本数据结构解析

1.二叉树结构


2.二叉搜索树结构


3.AVL平衡二叉查找数结构


4.红黑树(自平衡二叉查找树)

特征:(这样设计的初衷是为了时间复杂度的优化并且无论插入多少次 时间复杂度稳定在logn)
1.节点只有红色和黑色
2.根节点为黑
3.叶子节点为黑色的NIL节点
4.红节点的子节点一定为黑色节点
5.任意一条路径中的黑色节点个数一致
6.新插入的节点必须为红色(若违反以上5条就需要进行特殊的处理(修复))、
修复:
1.当前节点为红,并且父节点且叔父节点为红,那么将父节点以及叔父节点涂黑,然后将祖父节点涂红
2.当前节点为红,并且父节点为红且叔父节点为黑,当前节点为右子叶,以当前节点为轴进行左旋
3.当前节点为红,并且父节点为红且叔父节点为黑,当前节点为左子叶,以父节点为轴进行右旋
(若出现了1必出现2和3)
时间负责度:
红黑树可以在O(log n)时间内完成查找,插入和删除操作

5.B树与B+树(Mysql的索引的建立机制)


5.Concurrent工具包详解

1.阻塞式队列

1.ArrayBlockingQueue(阻塞式顺序队列)
2.LinkedBlockingQueue(阻塞式链式队列)
3.PriorityBlockingQueue(具有优先级的阻塞式队列)
4.SynchronousQueue(同步队列,只允许存储一个元素)

2.并发映射

1.ConcurrentHashMap(并发哈希映射)异步式线程安全的映射
jdk1.8之前 分段锁(读写锁)
jdk1.8以后 CAS无所算法
从jdk1.8开始,当桶中的元素个数超过8个,会将桶中
的链表扭转成一棵红黑树。如果桶中的元素个数不足7个,会将红黑树在扭转回链表。

3.并发导航映射

本身是一个接口,所以更多的是使用实现类 - ConcurrentSkipListMap - 并发跳跃表映射跳跃表:为了提高查询效率所产生一种数据结构 --- 跳跃表是典型的以空间换时间的
时间复杂度:O(logn)
适用场景:大量的查询而不增删的场景

4.锁

1.CountDownLatch(闭锁)(线程递减锁)
2.CyclicBarrier(珊栏)
3.Exchanger 交换机 用于交换两个线程之间的信息
4.Semaphore 信号量 用于计数 - 信号在被用完之后,后来的线程就会被阻塞,直到有信号被归还,被阻塞的线程才能取得信号继续执行
5.Lock(比synchronized更加灵活)
公平与非公平的策略:
公平(api可以设置)当前线程释放锁以后会处在队列中让其他线程抢占 然后继续放入队列 循环往复
非公平(默认):当前线程释放锁以后依然可以再次抢占
6.读写锁
读锁:不允许线程写(例如:增加,删除,更新),允许多个线程读
写锁:只允许一个线程写,不允许线程读

5.线程池(ExecutorService-执行器服务接口来实现)
(1)定义

线程池 - 如果每一个请求对应一个线程,那么会导致线程大量的创建和销
毁。减少线程的创建和销毁,希望能够重复使用已有的线程,有了线程
池 --- 存储线程的队列

(2)特点:

1.线程池在创建的时候是没有线程的·
2.当有请求过来的时候,线程池中才会创建一个线程来接受处理,当请求处理完毕之后,线程才回还回线程池,等待下一个请求
3.核心线程需要制定数量
4.核心线程占满后,引入工作队列,是一个阻塞式队列
5.都占满之后,引入临时线程去处理新的请求
(临时线程在处理完请求后不会立即销毁,会等待一段时间,如果没有新的请求,那么一段时间后销毁)

(3)Java中执行器服务来提供的线程池
1缓存线程池

 特点:
1. 没有核心线程,所有线程都是临时线程
2. 线程池的容量可以认为是无限的
3. 每一个临时线程存活时间都是1min - 存活时间不长
4.  工作队列是一个同步队列 - 只能存储一个元素
总结:
1.大池子小队列
2.理论上可以处理人一多的请求
3.适用于短任务场景,如:聊天
ExecutorService es = Executors.newCachedThreadPool();

2混合线程池

特点:
1.需要制定核心线程的数量
2.只有核心线程没有临时线程
3.工作队列是阻塞式链式队列,没有指定容量
总结:
1.小池子大队列
2.理论上可以存储任意多的请求
3.适用于长任务场景,如:文件下载
ExecutorService es = Executors.newFixedThreadPool(5)

3.ScheduledExecutorService 定时执行者服务
API

1.创建
ScheduledExecutorService ses = Executors.newScheduledThreadPool(5)
2.每5s执行一个线程
ses.cheduleWithFixedDelay(new 线程名(),initDelay,period,unit)
解释:以上一次线程的执行的起始时间为准开始计算 若线程执行时间超过了间隔时间 第二个线程就会等待第一个线程执行结束
3.每5s执行一个线程
ses.scheduleWithFixedDelay(new 线程名(),initDelay,period,unit)
解释:以上一次线程的执行的结束时间为准开始计算 
以上:initDelay是指在各自准备开启第二个线程时之前的等待时间,period表示等待多久,unit表示时间单位
4.使用定是执行服务可以做什么?
可以做:如:凌晨1点对数据进行数据更新

4.分叉合并:

1.分叉
大任务划分为小任务,发到cpu不用的核当中处理
2.合并
小任务分别执行完任务后进行合并
3.底层原理
工作窃取:
一个核上所有的线程执行完成后 挑一个核 从这个核的线程队列中偷取最后一个线程回来执行
4.带来问题
资源共享问题:两个核抢夺一个线程来执行


6.原子性操作

多线程环境中保证一系列的操作是单线程的操作没有其他线程干扰(例如i++非原子性操作,总共有3个步骤不能保证没有其他线程的干扰)
volatile(保证了多线程场景下的原子性)限定线程在执行过程中必须按照指定的指令顺序来执行
如何保证原子性
1.加锁
2.使用J.U.C下的atomic来实现原子操作

atomic原理
1.jdk1.8之前 volaile+锁
2.jdk1.8开始 volatile+CAS无锁算法(查看更新版本号)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值