Java多线程
2021-04-07 20:46:30 0 举报
AI智能生成
并发编程
作者其他创作
大纲/内容
线程与进程
进程
系统程序运行的基本单位
线程
线程是一个比进程更小的执行单位
线程引入是为了提高系统的执行效率
多线程
并行
单位时间内,多个任务同时执行
并发
同一时间段,多个任务都在执行 (单位时间内不一定同时执行)
线程的状态
NEW
初始状态,线程被构建,还没有调用start()方法
RUNABLE
运行状态,它包括就绪和运行中
BLOCKED
阻塞状态
WAITING
等待状态,表示线程进入等待状态,进入该状态标识需要等待其他线程做出操作(通知或中断)
TIME_WAITING
超时等待状态,不同于WAITING,在指定时间自行返回
TERMINATED
终止状态,表示线程执行完毕
多线程可能遇到的问题
线程安全
解决办法
无状态
使用final修饰,使其不可变
加锁
synchronized
volatile
ReentrantLock
CAS
JDK提供过的类
原子性Atomic
容器ConcurrentHashMap。。
性能问题
Thread
创建方式
继承Thread
Java不支持多继承
实现Runable
一般使用Runable接口
实现Callable
如果需要返回值,使用Callable
守护线程
守护线程是一个服务线程,没有服务对象就没有必要运行了
在线程启动前设置为守护线程,setDaemon(boolean on)
守护线程中创建的线程,也是守护线程
优先级
优先级高,仅仅表示获取时间片的几率高,并不是一个确定因素
高度依赖操作系统
方法
sleep()
调用sleep()会进入计时等待状态,时间到了的话,就会进入就绪状态,而非运行状态
yield()
先让别的线程执行,但不一定真的让出
join()
等待该线程执行完毕后才执行别的线程
interrupt()
不会真的停止线程,而是发出一个终止的信号,告诉它改结束了
仅仅是一个状态标识位
静态方法interrupt(),会清除中断标识位
实例方法IsInterrupt(),不会清除中断标识位
锁机制
synchronized
简介
Java关键字,可修饰方法、变量、代码块
是一种互斥锁,一次只允许一个线程进入到修饰的代码中
底层通过monitor对象,对象有自己的对象头,存储了线程id
用途
保证线程原子性
也可以保证可见性
类锁与对象锁
静态方法获取的是类锁
修饰普通方法或代码块,是对象锁
可重入
内部维护一个count,记录加锁
非公平锁
锁升级
JDK1.5后做的优化
无锁
偏向锁
轻量级锁
重量级锁
Lock
简介
Lock方式来获取锁支持中断、超时不获取、是非阻塞的
Lock显式锁提供了很灵活的加解锁的方法
支持Condition条件对象
AQS
特性
AbstractQueuedSynchronizer简称
是一个悲观锁框架
虚拟的双向队列CLH,先进先出
内部维护了状态state,使用了CAS
实现
ReentrantLock
比synchronized加解锁更加灵活
可以实现公平锁和非公平锁
lock.lockInterruptibly()可以中断
ReentrantReadWriteLock
在读的时候可以共享,在写的时候是互斥的
读锁不支持条件对象,写锁支持条件对象
读锁不能升级为写锁,写锁可以降级为读锁
在内部定义了两个内部类来代表读锁和写锁,本质上还是AQS实现
它使用state的变量高16位是读锁,低16位是写锁
CountDownLatch
CountDownLatch是一个同步工具类,用来协调多个线程之间的同步
让一些线程阻塞直到另一些线程完成一系列操作后才唤醒
CountDownLatch是一次性的,计算器的值只能在构造方法中初始化一次,之后没有任何机制再次对其设置值,当CountDownLatch使用完毕后,它不能再次被使用。
CyclicBarrier
让一组线程到达一个屏障时被阻塞,知道最后一个线程到达屏障,所有被屏障拦截的线程才会继续执行
子主题
Semaphore
信号量
控制线程的并发数量
Atomic
原子类可分为4种类型:基本数据类型、数组、引用类型、对象的属性
解决ABA问题可以使用AtomicStampedReference和AtomicMarkableReference类
LongAdder性能比AtomicLong要好
ThradLocal
ThreadLocal存储的变量属于当前线程,该变量对其他线程而言是不可见的
Thread为每个线程维护了ThreadLocalMap这么一个Map,而ThreadLocalMap的key是ThreadLocal对象本身,value则是要存储的对象
内存泄漏是因为key是一个弱引用,value是一个强引用,当发生GC时,key会被会后,就会产生一个null的key和value值得map,一直回收不了
想要避免内存泄露就要手动remove()掉
ThreadLocal设计的目的就是为了能够在当前线程中有属于自己的变量,并不是为了解决并发或者共享变量的问题
线程池
0 条评论
下一页