-
线程间的等待唤醒机制
线程之间的等待唤醒机制,也就是生产者消费者模式1.定义一个资源 2.要有一个生产线程 3.要有一个消费线程 4.测试类
等待唤醒:
作为生产者来说,有了资源,等着,通知消费线程来消费
作为消费线程,消费完了资源,通知生产线程来生产
Object
Object方法 | 功能 |
---|---|
void wait() | 在其他线程调用此对象的notify()方法前,导致当前线程等待。 |
void wait(long timeout) | 在其他线程调用此对象的notify()方法,或者超过指定的时间量前,导致当前线程等待 |
void notify() | 唤醒在此对象监视器上等待的单个线程 |
void notifyAll() | 唤醒在此对象监视器上等待的所有线程 |
- 内存可见性问题volatile
1.Java内存模型
想要理解volatile为什么能确保可见性,就要先理解Java中的内存模型是什么样的。
Java内存模型规定了所有的变量都存储在主内存中。每条线程中还有自己的工作内存,
线程的工作内存中保存了被该线程所使用到的变量(这些变量是从主内存中拷贝而来)。
线程对变量的所有操作(读取,赋值)都必须在工作内存中进行。
不同线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。
2.Java中的可见性
对于可见性,Java提供了volatile关键字来保证可见性。
当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
而普通的共享变量不能保证可见性,因为普通共享变量被修改之后,什么时候被写入主存是不确定的,
当其他线程去读取时,此时内存中可能还是原来的旧值,因此无法保证可见性。
另外,通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,
并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。
volatile 关键字:当多个线程进行操作共享数据时,可以保证内存中的数据可见。
相较于 synchronized 是一种较为轻量级的同步策略。
volatile 变量,用来确保将变量的更新操作通知到其他线程。
可以将 volatile 看做一个轻量级的锁,但是又与
锁有些不同:
对于多线程,不是一种互斥关系
不能保证变量状态的“原子性操作”
- CAS算法
1.CAS (Compare-And-Swap) 是一种硬件对并发。的支持,针对多处理器
操作而设计的处理器中的一种特殊指令,用于管理对共享数据的并
发访问。
- CAS 是一种无锁的非阻塞算法的实现。
- CAS 包含了 3 个操作数:
- 需要读写的内存值 V
- 进行比较的值 A
- 拟写入的新值 B
当且仅当 V 的值等于 A 时, CAS 通过原子方式用新值 B 来更新 V 的
值,否则不会执行任何操作。
jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的,这是一种独占锁,也是是悲观锁。
-
线程的状态转换图及常见执行情况
新建 , 就绪 , 运行 , 冻结 , 死亡
新建:线程被创建出来
就绪:具有CPU的执行资格,但是不具有CPU的执行权
运行:具有CPU的执行资格,也具有CPU的执行权
阻塞:不具有CPU的执行资格,也不具有CPU的执行权
死亡:不具有CPU的执行资格,也不具有CPU的执行权 -
线程池的概述和使用
线程池概述:线程池是一个容器,它里面的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
内置线程池的使用概述:
有几个方法
方法名 | 功能 |
---|---|
public static ExecutorService newCachedThreadPool(): | 根据任务的数量来创建线程对应的线程个数 |
public static ExecutorService newFixedThreadPool(int nThreads): | 固定初始化几个线程 |
public static ExecutorService newSingleThreadExecutor(): | 初始化一个线程的线程池 |
这些方法的返回值都是ExecutorService对象,该对象表示一个线程池,可以执行Runnable对象或者Callable对象的线程。它提供了以下方法
Future<?> submit(Runnable task)
Future submit(Callable task)
使用步骤:
创建线程池对象
创建Runnable实例
提交Runnable实例
关闭线程池
public static ExecutorService newCachedThreadPool这个是你创建多少个就会有多少个不同的线程
- 匿名内部类实现多线程
匿名内部类实现多线程,有两种方法。如果仅仅使用一次多线程的话,可以使用这个匿名内部类来实现
第一种
第二种
,