Java多线程基础入门
文章目录
1)基本概念
2)多线程的使用
3)synchronized与volatile关键字
基本概念
- 进程和线程
- 进程是程序的一次执行过程,是系统运行程序的基本单位
- 线程是轻量级进程,程序执行的最小单位,线程间的切换和调度的成本远远小于进程
- 多线程是多个线程同时运行或交替运行
- 开发高并发系统,利用多线程机制可以大大提高系统整体的并发能力以及性能
- 同步和异步
- 同步开始之后,调用者必须等到方法调用返回后,才能继续后续的行为。
- 异步调用更像一个消息传递,一旦开始,方法调用就会立刻返回,调用者可以继续后续的操作。
- 并发和并行
- 并发偏重于多个任务交替执行,而多个任务之间有可能还是串行,并行是真正意义上的同时执行
- 高并发的指标有响应时间、吞吐量、每秒查询率、并发用户数等
- 临界区
- 表示一种公共资源或是共享数据,可以被多个线程使用
多线程的使用
1.继承Thread类
2.实现Runable接口
3.使用线程池
- 常用方法
currentThread()
- 返回当前正在执行的线程对象的引用
getId()
- 返回此线程的标志符
getName()
- 返回此线程的名称
getPriority()
- 返回此线程的优先级
isAlive
- 测试这个线程是否处于活动状态
sleep(long millis)
- 使当前线程以指定毫秒数休眠
interrupt()
- 中断这个线程
- …
- 停止线程:.isInterrupted() 然后return
- 线程的优先级
- 线程的优先级可以再程序中表明该线程的重要性
- 线程优先级具有继承特性
- 线程优先级具有随机性
- 线程优先级搞得不一定每一次都先执行完
- 线程分类
- 1.用户线程
- 2.守护线程
.setDaemon(true)
再.start()
方法前执行- 在守护线程中产生的新线程也是守护线程
- 读写操作或者计算逻辑不能分配给守护线程来执行
- 等待通知机制
- 不使用的话,如果轮询时间的间隔太小会浪费CPU资源,轮询时间的间隔太大,可能就取不到自己想要的数据
wait()
和notify()/notifyAll()
,用来完成等待方和通知方之间的交互工作notify()
随机唤醒等待队列中等待同一共享资源的一个线程,并使该线程退出等待队列,进入可运行状态wait()
使用该方法的线程释放共享资源锁,然后从运行状态退出,进入等待队列notify()
执行后并不会立即释放锁- 在方法wait()被执行后,锁被自动释放,但执行完notify()方法后,锁不会自动释放,必须执行完notify()方法所在的synchronized代码块后才释放
- 线程的基本状态
- new (新建)
- runnable (可运行)
- running (可运行)
- block (阻塞)
- dead (死亡)
synchronized与volatile关键字
- 1).synchronized
- 解决多个线程之间访问资源的同步性,被它修饰的代码块在同一时刻只能有一个线程执行。
- 双重校检锁实现对象单例
- new 分三步执行
- 单例 整个程序有且仅有一个实例,该类负责创建自己的对象,同时确保只有一个对象被创建。
- 2).volatile
- 性能比synchronized要好,volatile关键字只能用于变量,synchronized关键字可以修饰方法以及代码块
- 多线程访问volatile关键字不会发生阻塞,而synchronized关键字可能会发生阻塞。
- volatile关键字能保证数据的可见性,但不能保证数据的原子性。synchronized关键字两者都能保证。
- volatile关键字主要用于解决变量在多个线程之间的可见性,而synchronized关键字解决的是多个线程之间访问资源的同步性。
- volatile类型的变量禁止指令重排序优化
- volatile变量的读操作和普通变量的读操作几乎没有差异,但是写操作会性能差一些,慢一些。
参考
《Java并发编程的艺术》
java中的守护线程
Java多线程学习(四)等待/通知(wait/notify)机制
BATJ都爱问的多线程面试题