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