线程的优先级
public static void main(String[] args){
Thread thread = new Thread();
thread.start();
int ui_proi = Process.getThreadPriority(0)
int th_proi = thread.getPriority();
//输出成果
ui_proi = 5
th_proi = 5
}
1.线程的优先级是具有承继性的,在某个线程中创立的线程会承继线程的优先级。例如咱们在UI线程中创立了线程,则线程优先级和UI线程优先级相同,相等的和UI线程抢占CPU时刻资源。
2.JDKAPI 中约束了新设置的线程优先级有必要为[1~10], 优先级priority越高,获取CPU时刻片段的概率越高。
java.lang.Thread.setPriority(int newPriority)
3.Android API 能够为线程设置愈加精密的优先级(-20~19)优先级priority的值越低,获取CPU时刻片的概率越高。
android.os.Process.setThreadPriority(int newPriority)
线程的状况
NEW 初始状况,线程被新建,还没调用start办法
RUNNABLE 运转状况,把“运转中”和“就绪”统称为运转状况
BLOCKED 堵塞状况,表明线程堵塞于锁
WAITING 等候状况,需求其他线程告诉唤醒
TIME_WAITING 超时等候状况,表明能够在指定的时刻超时后自行返回
TERRMINATED 终止状况,表明当前线程已履行完毕
下图表明线程各种状况间的切换
wait 线程进入等候
wait关键字能使线程进入等候,开释线程锁
/**================================================================
* wait关键字
* wait关键字能使线程进入等候,开释线程锁,抱负状况下thread1应该先履行,履行进入wait办法后开释线程锁,thread得以继续向下履行,唤醒线程1继续履行
* 日志应该为
* RUN1---start
* RUN2---start
* RUN1---end
* RUN2---end
* 可是无法确定线程1或线程2谁先履行,若线程2 先履行,线程1履行wait办法后将进入等候且无人唤醒,所以需求加原子变量操控
* 实践日志
*
D/ThreadTestForJava: RUN2---start1644565101644
D/ThreadTestForJava: RUN2---end1644565101644
D/ThreadTestForJava: RUN1---start1644565101645
* ================================================================
*/
Object obj = new Object();
class Runable1 implements Runnable{
@Override
public void run() {
Log.d(TAG, "RUN1---start" + System.currentTimeMillis());
synchronized (obj){
try {
if(isWait){
obj.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.d(TAG, "RUN1---end" + System.currentTimeMillis());
}
}
class Runable2 implements Runnable{
@Override
public void run() {
Log.d(TAG, "RUN2---start" + System.currentTimeMillis());
synchronized (obj){
isWait = false;
obj.notify();
}
Log.d(TAG, "RUN2---end" + System.currentTimeMillis());
}
}
public void waitTest(){
Thread thread1 = new Thread(new Runable1());
Thread thread2 = new Thread(new Runable2());
thread1.start();
thread2.start();
}
join关键字
join关键字的效果是等候目标线程履行完后再履行此线程
/**
* ===============================================================================
* join关键字
* 等候目标线程履行完后在履行此线程
* 正常状况先,runable4应该先履行完,然后runable3会等候10秒后才干走完,在runable4中调用join办法,runable4将会等候runable3走完才继续履行
* 未参加join
* D/ThreadTestForJava: RUN4---start1644566194613
* D/ThreadTestForJava: RUN4---end1644566194614
* D/ThreadTestForJava: RUN3---start1644566194614
* D/ThreadTestForJava: RUN3---end1644566204616
* 参加join
* D/ThreadTestForJava: RUN3---start1644566395452
* D/ThreadTestForJava: RUN4---start1644566395453
* D/ThreadTestForJava: RUN3---end1644566405455
* D/ThreadTestForJava: RUN4---end1644566405458
* ===============================================================================
*/
Thread thread3 = new Thread(new Runable3());
Thread thread4 = new Thread(new Runable4());
class Runable3 implements Runnable{
@Override
public void run() {
Log.d(TAG, "RUN3---start" + System.currentTimeMillis());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "RUN3---end" + System.currentTimeMillis());
}
}
class Runable4 implements Runnable{
@Override
public void run() {
Log.d(TAG, "RUN4---start" + System.currentTimeMillis());
try {
thread3.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "RUN4---end" + System.currentTimeMillis());
}
}
public void joinTest(){
thread3.start();
thread4.start();
}
sleep关键字
/**
* sleep关键字
* sleep关键字使调用线程进入休眠状况,但在一个synchronized中履行sleep,线程虽然会休眠,可是不会开释资源锁
* 若runable5先运转,则ruanable6要比及runable5sleep完结才干履行同步代码块中的代码
* D/ThreadTestForJava: RUN5---start1644567514833
* D/ThreadTestForJava: RUN5---end1644567524837
* D/ThreadTestForJava: RUN6---start1644567524838
* D/ThreadTestForJava: RUN6---end1644567524840
*/
class Runable5 implements Runnable{
@Override
public void run() {
Log.d(TAG, "RUN5---start" + System.currentTimeMillis());
synchronized (obj){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.d(TAG, "RUN5---end" + System.currentTimeMillis());
}
}
class Runable6 implements Runnable{
@Override
public void run() {
synchronized (obj){
Log.d(TAG, "RUN6---start" + System.currentTimeMillis());
Log.d(TAG, "RUN6---end" + System.currentTimeMillis());
}
}
}
public void sleepTest(){
Thread thread3 = new Thread(new Runable5());
Thread thread4 = new Thread(new Runable6());
thread3.start();
thread4.start();
}
主线程向子线程通讯
/**
* ===============================================================
* 主线程向子线程通讯
* 日志
* D/ThreadTestForJava: Thread: 123
* 子线程需求自己保护loop
* Looper.prepare();
* synchronized (HandlerThread.this){
* looper = Looper.myLooper();
* notify();
* }
* Looper.loop();
*为了避免looper为空,所以在获取loop的办法中参加wait,可是在主线程等候时刻过长会引发RNA,所以先要调用start在去获取looper
* ===============================================================
*/
class HandlerThread extends Thread{
public HandlerThread(){
super("123");
}
private Looper looper;
public Looper getLooper() {
synchronized (HandlerThread.this){
if(looper == null && !isAlive()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return looper;
}
@Override
public void run(){
Looper.prepare();
synchronized (HandlerThread.this){
looper = Looper.myLooper();
notify();
}
Looper.loop();
}
}
public void testHandlerThread(){
HandlerThread handlerThread = new HandlerThread();
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper()){
@Override
public void handleMessage(Message msg){
super.handleMessage(msg);
Log.d(TAG, "Thread: " + Thread.currentThread().getName());
}
};
handler.sendEmptyMessage(1);
}
fun testAtomic(){
val runable = Runnable {
for (i in 0 until 10000){
ThreadSafeTest.addAtomic()
ThreadSafeTest.addVolatile()
}
}
val thread1 = Thread(runable)
val thread2 = Thread(runable)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
println("atomicCount ${ThreadSafeTest.atomicCount.get()}")
println("count ${ThreadSafeTest.count}")
}
线程锁与Volatile
java中线程锁能够根据功用分类为以下几种
其实首要便是 Synchronized 和 ReentrantLock
Atomic
原子类和Volatile
原子类,CAS 完结无锁数据更新,自旋的设置能够有用避免线程因堵塞-唤醒带来的体系资源开支
适用场景:多线程计数,原子操作,并发数量小的场景
Volatile润饰的成员变量在每次线程拜访时,都逼迫从同享内存从头读取该成员的值,并且,当成员变量值发生改变时,逼迫将改变的值从头写入同享内存。
不能解决非原子操作的线程安全性。功能不及原子类高。
/**
*原子类和volatile润饰
* 原子类完结无锁更新,自旋的规划能够有用避免线程堵塞,唤醒带来的资源浪费
* 适用于多线程计数,原子操作,并发数量小,读操作多的场景
* volatile润饰的成员变量在每次线程拜访时,都逼迫从同享内存从头读取该成员的值,并且,当成员变量值发生改变时,逼迫改变的值从头写入同享内存
* 非原子操作对其他线程不可见
*
* 在下面的代码中,两个线程分别对原子类和Volatile润饰的成员变量++,最终成果应该都是20000
* 可是Volatile润饰的成员变量最终成果却不是20000,这是由于其他线程无法拿到非原子操作后的值,导致自增犯错
*
*
* atomicCount 20000
count 17974
*/
object ThreadSafeTest {
val atomicCount : AtomicInteger = AtomicInteger()
@Volatile
var count = 0
fun addAtomic(){
atomicCount.getAndIncrement()
}
fun addVolatile(){
count++
}
}
Synchronized线程锁
- 锁办法,加在办法上,未获取到目标锁的其他线程都不能够拜访该办法。(如果多个实例还是会呈现线程问题)
synchronized void printThreadName(){}
- 锁class目标,家在static办法上相当于给Class目标加锁,哪怕是不同的java目标实例,也需求排队履行
static synchronized void printThreadName(){}
- 锁代码块,未获取到目标锁的其他线程能够履行代码块之外的代码
void printThreadNam(){
String name = Thread.currentThread().getName();
System.out.print("线程" + name + "预备好了");
synchronized(this){
}
}
/**
*1.无任何线程安全的状况下,五个线程一起拜访printTick
* 代码如下
* fun printTick(){
println("Thread_${Thread.currentThread().name}预备好了。。。")
Thread.sleep(1000)
println("Thread_${Thread.currentThread().name}买了${ticks.removeAt(0)}")
}
*
* 成果入下
Thread_Thread-0预备好了。。。
Thread_Thread-2预备好了。。。
Thread_Thread-4预备好了。。。
Thread_Thread-1预备好了。。。
Thread_Thread-3预备好了。。。
Thread_Thread-0买了第0张票
Thread_Thread-2买了第0张票
Thread_Thread-1买了第3张票
Thread_Thread-4买了第0张票
Thread_Thread-3买了第0张票
*呈现重复购票
* 2.在办法上加了同步锁
@Synchronized
fun printTick(){
println("Thread_${Thread.currentThread().name}预备好了。。。")
Thread.sleep(1000)
println("Thread_${Thread.currentThread().name}买了${ticks.removeAt(0)}")
}
成果如下
Thread_Thread-0预备好了。。。
Thread_Thread-0买了第0张票
Thread_Thread-4预备好了。。。
Thread_Thread-4买了第1张票
Thread_Thread-3预备好了。。。
Thread_Thread-3买了第2张票
Thread_Thread-2预备好了。。。
Thread_Thread-2买了第3张票
Thread_Thread-1预备好了。。。
Thread_Thread-1买了第4张票
同步代码块中的代码值答应一个线程拜访,这个锁仅仅目标锁,调用不同目标的同步办法,也会呈现线程不安全的状况
for(i in 0 until 5){
Thread(Runnable {
SynchronizedTest().printTick()
}).start()
}
不同目标调用同步锁的代码
Thread_Thread-0预备好了。。。
Thread_Thread-3预备好了。。。
Thread_Thread-2预备好了。。。
Thread_Thread-1预备好了。。。
Thread_Thread-4预备好了。。。
Thread_Thread-0买了第0张票
Thread_Thread-2买了第0张票
Thread_Thread-4买了第0张票
Thread_Thread-3买了第0张票
Thread_Thread-1买了第0张票
无法起到线程安全
3.若同步锁放在静态办法上则会锁住class,在jvm中class只要一份,所以不同目标也会线程安全
4.若同步锁只效果与部分代码块,则不在同步代码块中的代码将无法确保线程安全,同步代码块之后的办法也能够取得线程安全
fun printTick(){
println("Thread_${Thread.currentThread().name}预备好了。。。")
synchronized(this){
Thread.sleep(1000)
println("Thread_${Thread.currentThread().name}买了${ticks.removeAt(0)}")
}
println("Thread_${Thread.currentThread().name}完毕了。。。")
}
Thread_Thread-1预备好了。。。
Thread_Thread-3预备好了。。。
Thread_Thread-2预备好了。。。
Thread_Thread-0预备好了。。。
Thread_Thread-4预备好了。。。
Thread_Thread-1买了第0张票
Thread_Thread-1完毕了。。。
Thread_Thread-4买了第1张票
Thread_Thread-4完毕了。。。
Thread_Thread-0买了第2张票
Thread_Thread-0完毕了。。。
Thread_Thread-2买了第3张票
Thread_Thread-2完毕了。。。
Thread_Thread-3买了第4张票
Thread_Thread-3完毕了。。。
synchronized优势,无需关怀开释锁,jvm会为咱们自动开释,
下风:有必要比及获取锁目标线程履行完结,或许呈现异常,才干开释掉,不能中途开释,不能中止一个正在
企图取得锁的线程,别的也不知道多个线程竞赛锁的时分获取锁成功与否,每个锁仅有单一的条件,不能设定超时
*/
class SynchronizedTest(){
companion object{
val ticks = mutableListOf<String>()
}
fun printTick(){
println("Thread_${Thread.currentThread().name}预备好了。。。")
synchronized(this){
Thread.sleep(1000)
println("Thread_${Thread.currentThread().name}买了${ticks.removeAt(0)}")
}
println("Thread_${Thread.currentThread().name}完毕了。。。")
}
init {
for(i in 0 until 5){
ticks.add("第${i}张票")
}
}
}
fun testSynchronized(){
val synchronizedTest = SynchronizedTest()
for(i in 0 until 5){
Thread(Runnable {
synchronizedTest.printTick()
}).start()
}
}
synchronized的优势
- 哪怕咱们同步办法中呈现异常,jvm也能够为咱们自动开释锁,能自动从而规避死锁。不需求开发者手动开释锁 下风
- 有必要要比及获取锁的目标的线程履行完结,或许呈现异常,才干开释掉。不能中途开释锁,不能中止一个正在企图取得锁的进程
- 别的也不知道多个线程竞赛锁的时分,获取锁成功与否,所以不够灵活
- 每个锁仅有单一的条件(某个目标)不能设定超时。
ReentrantLock 悲观锁,可重入锁,公正锁,非公正锁
- 根本用法
ReentrantLock lock = new ReentrantLock()
try{
lock.lock()
}finally{
lock.unLock()
}
void lock()//获取不到会堵塞
boolean tryLock()//测验获取锁,成功返回true。
boolean tryLock(3000, TimeUnit.MILLISECONDS)//在必定时刻内不断去测验获取锁
void lockInterruptibly();//可运用Thread.interrupt()打断堵塞状况,退出竞赛,让给其他线程
- 可重入,避免死锁
ReentrantLock lock = new ReentrantLock()
public void doWork(){
try{
lock.lock()
doWork();//递归,使得统一线程屡次取得锁
}finally{
lock.unLock()
}
}
/**
* 可重入锁
* 答应同一个线程在不开释锁的状况下,再次获取锁,避免锁死
打印第一张 Thread-0
打印第二张 Thread-0
打印第三张 Thread-0
打印第四张 Thread-0
打印第五张 Thread-0
打印第一张 Thread-2
打印第二张 Thread-2
打印第三张 Thread-2
打印第四张 Thread-2
打印第五张 Thread-2
打印第一张 Thread-7
打印第二张 Thread-7
打印第三张 Thread-7
打印第四张 Thread-7
打印第五张 Thread-7
打印第一张 Thread-3
打印第二张 Thread-3
打印第三张 Thread-3
打印第四张 Thread-3
打印第五张 Thread-3
打印第一张 Thread-6
打印第二张 Thread-6
打印第三张 Thread-6
打印第四张 Thread-6
打印第五张 Thread-6
打印第一张 Thread-5
打印第二张 Thread-5
打印第三张 Thread-5
打印第四张 Thread-5
打印第五张 Thread-5
打印第一张 Thread-9
打印第二张 Thread-9
打印第三张 Thread-9
打印第四张 Thread-9
打印第五张 Thread-9
打印第一张 Thread-1
打印第二张 Thread-1
打印第三张 Thread-1
打印第四张 Thread-1
打印第五张 Thread-1
打印第一张 Thread-8
打印第二张 Thread-8
打印第三张 Thread-8
打印第四张 Thread-8
打印第五张 Thread-8
打印第一张 Thread-4
打印第二张 Thread-4
打印第三张 Thread-4
打印第四张 Thread-4
打印第五张 Thread-4
*/
class ReentrantLock2{
val lock = ReentrantLock()
fun simpleUse(){
try{
lock.lock()
println("打印第一张 ${Thread.currentThread().name}")
Thread.sleep(1000)
lock.lock()
println("打印第二张 ${Thread.currentThread().name}")
Thread.sleep(1000)
lock.lock()
println("打印第三张 ${Thread.currentThread().name}")
Thread.sleep(1000)
lock.lock()
println("打印第四张 ${Thread.currentThread().name}")
Thread.sleep(1000)
lock.lock()
println("打印第五张 ${Thread.currentThread().name}")
Thread.sleep(1000)
}finally {
/**
* 加锁几次,就要解锁几次
*/
lock.unlock()
lock.unlock()
lock.unlock()
lock.unlock()
lock.unlock()
}
}
}
/**
* 可重入锁
*/
private fun test2(){
val lockTest2 = ReentrantLockTest.ReentrantLock2()
val run = Runnable {
lockTest2.simpleUse()
}
for(i in 0 until 10){
Thread(run).start()
}
}
- 公正锁与非公正锁
- 公正锁,一切进入堵塞的线程呢排队一次均有时机履行
- 默认非公正锁,答应线程插队,避免每个线程都进入堵塞,在唤醒,功能高,由于线程能够插队,导致行列中或许存在线程饿死的状况,一向得不到锁,一向得不到履行
ReentrantLock lock = new ReentrantLock(true/false)
/**
* ReentrantLock默认为非公正锁
* 公正锁:一切进入堵塞的线程排队一次均有时机履行
* 非公正锁:答应线程插队,避免每一个线程都进入堵塞,在唤醒,功能高。由于线程能够插队,导致行列中或许会存在线程饿死的状况,一向得不到锁,一向得不到履行
* 可重入锁:答应同一个线程在不开释锁的状况下,再次获取锁,避免锁死
*/
/**
* 公正锁---非公正锁
* 运用非公正锁,在线程中开释了锁又当即获取锁,会优先履行
打印第一张 Thread-0
打印第二张 Thread-0
打印第一张 Thread-4
打印第二张 Thread-4
打印第一张 Thread-9
打印第二张 Thread-9
打印第一张 Thread-8
打印第二张 Thread-8
打印第一张 Thread-7
打印第二张 Thread-7
打印第一张 Thread-2
打印第二张 Thread-2
打印第一张 Thread-5
打印第二张 Thread-5
打印第一张 Thread-1
打印第二张 Thread-1
打印第一张 Thread-6
打印第二张 Thread-6
打印第一张 Thread-3
打印第二张 Thread-3
**
* 运用公正锁,每个线程都有相同的时机获取锁,线程一旦开释了锁,那么就会进入等候,将锁给予其他线程
打印第一张 Thread-1
打印第一张 Thread-9
打印第一张 Thread-4
打印第一张 Thread-3
打印第一张 Thread-5
打印第一张 Thread-6
打印第一张 Thread-0
打印第一张 Thread-7
打印第一张 Thread-8
打印第一张 Thread-2
打印第二张 Thread-1
打印第二张 Thread-9
打印第二张 Thread-4
打印第二张 Thread-3
打印第二张 Thread-5
打印第二张 Thread-6
打印第二张 Thread-0
打印第二张 Thread-7
打印第二张 Thread-8
打印第二张 Thread-2
*/
class ReentrantLock1{
val lock = ReentrantLock(true)
fun simpleUse(){
try{
lock.lock()
println("打印第一张 ${Thread.currentThread().name}")
Thread.sleep(1000)
lock.unlock()
lock.lock()
println("打印第二张 ${Thread.currentThread().name}")
}finally {
lock.unlock()
}
}
}
/**
* 公正锁,非公正锁
*/
private fun testSimpleUns(){
val lockTest1 = ReentrantLockTest.ReentrantLock1()
val run = Runnable {
lockTest1.simpleUse()
}
for(i in 0 until 10){
Thread(run).start()
}
}
- Condition条件唤醒
- 可运用它的awit-singnal指定唤醒一个线程。比较于wait-notify要么悉数唤醒,要么只能唤醒一个,愈加灵活可控。
ReentrantLock lock = new ReentrantLock()
Condition worker1 = lock.newCondition();
Condition worker2 = lock.newCondition();
class Worker1{
worker1.awit()//进入堵塞,等候唤醒
}
class Worker2{
worker2.awit()//进入堵塞,等候唤醒
}
class Boss{
if(...){
worker1.signal()//指定唤醒线程1
}else{
worker2.signal()//指定唤醒线程2
}
}
/**
* 运用Condition条件目标,精密操控ReentrantLock
* 可运用它的await-singnal指定唤醒一个线程,比较wait-notify要么悉数唤醒,要么智能唤醒一个,愈加灵活
* 案例,出产者线程产生数据,偶数唤醒线程1,基数唤醒线程2
* await会开释锁,所以出产者线程中也需求参加Condition
*
没砖了,work1开端歇息了
没砖了,work2开端歇息了
出产出来了workNumber44,唤醒work2
work2开端搬砖: workNumber:44
work2开释锁
没砖了,work2开端歇息了
出产出来了workNumber98,唤醒work2
work2开端搬砖: workNumber:98
work2开释锁
没砖了,work2开端歇息了
出产出来了workNumber63,唤醒work1
work1开端搬砖: workNumber:63
work1开释锁
没砖了,work1开端歇息了
出产出来了workNumber13,唤醒work1
work1开端搬砖: workNumber:13
work1开释锁
没砖了,work1开端歇息了
出产出来了workNumber3,唤醒work1
work1开端搬砖: workNumber:3
work1开释锁
没砖了,work1开端歇息了
出产出来了workNumber9,唤醒work1
work1开端搬砖: workNumber:9
work1开释锁
没砖了,work1开端歇息了
出产出来了workNumber73,唤醒work1
work1开端搬砖: workNumber:73
work1开释锁
没砖了,work1开端歇息了
出产出来了workNumber27,唤醒work1
work1开端搬砖: workNumber:27
work1开释锁
没砖了,work1开端歇息了
出产出来了workNumber97,唤醒work1
work1开端搬砖: workNumber:97
work1开释锁
没砖了,work1开端歇息了
出产出来了workNumber63,唤醒work1
work1开端搬砖: workNumber:63
work1开释锁
没砖了,work1开端歇息了
*/
class ReentrantLock3{
@Volatile
var workNumber = 0
val lock = ReentrantLock(false)
val condition1 = lock.newCondition()
val condition2 = lock.newCondition()
val condition3 = lock.newCondition()
fun work1(){
try {
lock.lock()
if(workNumber == 0 || workNumber % 2 == 0) {
println("没砖了,work1开端歇息了")
condition1.await()
condition3.signal()
}
println("work1开端搬砖: workNumber:${workNumber} ")
workNumber = 0
}finally {
println("work1开释锁")
lock.unlock()
}
}
fun work2(){
try {
lock.lock()
if(workNumber == 0 || workNumber % 2 != 0){
println("没砖了,work2开端歇息了")
condition2.await()
condition3.signal()
}
println("work2开端搬砖: workNumber:${workNumber} ")
workNumber = 0
}finally {
println("work2开释锁")
lock.unlock()
}
}
fun boos(){
try {
lock.lock()
workNumber = (0..100).random()
if(workNumber % 2 == 0){
condition2.signal()
println("出产出来了workNumber${workNumber},唤醒work2")
}else{
condition1.signal()
println("出产出来了workNumber${workNumber},唤醒work1")
}
condition3.await()
}finally {
lock.unlock()
}
}
}
/**
* Condition条件唤醒
*/
private fun test3(){
val count = AtomicInteger()
val lockTest3 = ReentrantLockTest.ReentrantLock3()
Thread(Runnable {
count.getAndIncrement()
while(true){
lockTest3.work1()
}
}).start()
Thread(Runnable {
count.getAndIncrement()
while (true){
lockTest3.work2()
}
}).start()
Thread.sleep(1000)
for(i in 0 until 10){
lockTest3.boos()
}
}
- ReentrantReadWriteLock 同享锁,排他说
- 同享锁,一切线程均可一起取得,并发量高,比方在线检查文档
- 排他锁,同一时刻只要一个线程有权修正资源,比方在线文档编辑
ReentrantReadWriteLock reentrantReadWriteLock
ReentrantReadWriteLock.ReadLock readLock
ReentrantReadWriteLock.WriteLock writeLock
/**
* 同享锁,一切线程均可一起取得,并发量高,比方在线文档检查
* 排他锁,同一时刻只要一个线程有权修正资源,比方在线文档编辑
Thread Thread-2 开端写
Thread Thread-2 开释写锁
Thread Thread-6 开端写
Thread Thread-6 开释写锁
Thread Thread-3 开端写
Thread Thread-3 开释写锁
Thread Thread-7 开端写
Thread Thread-7 开释写锁
Thread Thread-1 开端写
Thread Thread-1 开释写锁
Thread Thread-4 开端写
Thread Thread-4 开释写锁
Thread Thread-9 开端写
Thread Thread-9 开释写锁
Thread Thread-0 开端写
Thread Thread-0 开释写锁
Thread Thread-8 开端写
Thread Thread-8 开释写锁
Thread Thread-5 开端写
Thread Thread-5 开释写锁
Thread Thread-2 开端阅览
Thread Thread-4 开端阅览
Thread Thread-6 开端阅览
Thread Thread-0 开端阅览
Thread Thread-5 开端阅览
Thread Thread-1 开端阅览
Thread Thread-7 开端阅览
Thread Thread-3 开端阅览
Thread Thread-9 开端阅览
Thread Thread-8 开端阅览
Thread Thread-5 开释读锁
Thread Thread-6 开释读锁
Thread Thread-2 开释读锁
Thread Thread-0 开释读锁
Thread Thread-1 开释读锁
Thread Thread-9 开释读锁
Thread Thread-7 开释读锁
Thread Thread-3 开释读锁
Thread Thread-8 开释读锁
Thread Thread-4 开释读锁
*/
class ReentrantReadWriteLockTest{
val reentrantReadWriteLock = ReentrantReadWriteLock()
val reentrantReadLock = reentrantReadWriteLock.readLock()
val reentrantWriteLock = reentrantReadWriteLock.writeLock()
fun readWork(){
try{
reentrantReadLock.lock()
println("Thread ${Thread.currentThread().name} 开端阅览")
Thread.sleep(1000)
}finally {
println("Thread ${Thread.currentThread().name} 开释读锁")
reentrantReadLock.unlock()
}
}
fun writeWork(){
try{
reentrantWriteLock.lock()
println("Thread ${Thread.currentThread().name} 开端写")
Thread.sleep(1000)
}finally {
println("Thread ${Thread.currentThread().name} 开释写锁")
reentrantWriteLock.unlock()
}
}
}
/**
* 排他锁
* 同享锁
*/
private fun test4(){
val reentrantReadWriteLockTest = ReentrantLockTest.ReentrantReadWriteLockTest()
for(i in 0 until 10){
Thread(Runnable {
reentrantReadWriteLockTest.readWork()
}).start()
}
// for(i in 0 until 10){
// Thread(Runnable {
// reentrantReadWriteLockTest.writeWork()
// }).start()
// }
}
如何正确运用锁&原子类
- 减少持锁时刻
尽管锁在同一时刻只能答应一个线程持有,其他想要占用锁的线程都在临界区外等候锁开释,这个等候的时刻根据实践的运用及代码写法可长可短
public void syncMethod(){ noneLockedCode();//2s synchronized(this){ needLockedMethed();//2s } noneLockedCode2;//2s }
- 锁分离 读读,读写,写读,写写。只要有些锁进入才需求做同步处理,可是关于大多数运用,读的场景远大于写。因此运用读写锁,在读多写少的场景中,就能够很好的进步体系的功能。这便是锁分离
- 锁粗化 屡次加锁
public void doSomethingMethod(){
synchronized(lock){
//do some thing
}
...
//这儿还有一些代码,做其他不需求同步的工作,单能很快履行完结
...
synchronized(lock){
//do other thing
}
}
//粗化
public void doSomethingMethod(){
synchronized(lock){
//do some thing
...
//这儿还有一些代码,做其他不需求同步的工作,单能很快履行完结
...
//do other thing
}
}
其他操控
CountDownLatch
/**
Thread 开端运转Thread-3
Thread 开端运转Thread-4
Thread 开端运转Thread-2
Thread 开端运转Thread-1
Thread 开端运转Thread-0
Thread 完毕运转Thread-2
Thread 完毕运转Thread-3
Thread 完毕运转Thread-4
Thread 完毕运转Thread-0
Thread 完毕运转Thread-1
一切线程运转完毕
CountDownLatch创立时需求指定一个int值,调用await的线程将被堵塞,直到其他线程调用countDown()办法将指定int值减为0时才干回复运转
*/
private fun countDownLatchTest(){
val countDownLatch = CountDownLatch(5)
for(i in 0 until 5){
Thread(Runnable {
println("Thread 开端运转${Thread.currentThread().name}")
Thread.sleep((2000 .. 6000).random().toLong())
println("Thread 完毕运转${Thread.currentThread().name}")
countDownLatch.countDown()
}).start()
}
countDownLatch.await()
println("一切线程运转完毕").run { }
countDownLatch.let { }
}
Semaphore
/**
Thread 开端运转Thread-1
Thread 开端运转Thread-0
Thread 开端运转Thread-5
Thread 完毕运转Thread-0
Thread 开端运转Thread-2
Thread 完毕运转Thread-1
Thread 开端运转Thread-3
Thread 完毕运转Thread-5
Thread 开端运转Thread-7
Thread 完毕运转Thread-3
Thread 开端运转Thread-9
Thread 完毕运转Thread-7
Thread 开端运转Thread-6
Thread 完毕运转Thread-2
Thread 开端运转Thread-8
Thread 完毕运转Thread-8
Thread 开端运转Thread-4
Thread 完毕运转Thread-6
Thread 完毕运转Thread-9
Thread 完毕运转Thread-4
Semaphore类似与令牌,创立时需指定令牌数量和是否时公正的,当一个线程运用semaphore.acquire()获取到令牌后能够继续履行,
当令牌被获取完后需求等候其他线程开释令牌才干运转
*/
private fun semaphoreTest(){
val semaphore = Semaphore(3, true)
for(i in 0 until 10){
Thread(Runnable {
semaphore.acquire()
println("Thread 开端运转${Thread.currentThread().name}")
Thread.sleep((2000 .. 6000).random().toLong())
println("Thread 完毕运转${Thread.currentThread().name}")
semaphore.release()
}).start()
}
}