线程安全的本质是 能够让并发线程有序的运行(这个有序有可能是先来后到排队,有可能有人插队,但不管怎么着,同一时刻只能一个线程有权访问同步资源),线程执行的结果,能够对其他线程可见。
import java.util.concurrent.atomic.AtomicInteger;
/**
* 一个用原子类修饰,一个用volatile修饰,在多线程的情况做自增,然后输出最后得值
*/
public class AtomicDemo {
public static void main(String[] args) throws InterruptedException {
final AtomicTask task = new AtomicTask();
Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
task.incrementVolatile();
task.incrementAtomic();
}
}
};
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("原子类的结果:" + task.atomicInteger.get());
System.out.println("volatile修饰的结果:" + task.volatileCount);
}
static class AtomicTask {
AtomicInteger atomicInteger = new AtomicInteger();
volatile int volatileCount = 0;
void incrementAtomic() {
atomicInteger.getAndIncrement();
}
void incrementVolatile() {
volatileCount++;
//volatileCount = volatileCount + 1;
//volatileCount = 10000;
}
}
}
import java.util.concurrent.locks.ReentrantLock;
/**
* 演示 多个线程去竞争锁的 用法
*/
public class ReentrantLockDemo {
static class ReentrantLockTask {
ReentrantLock reentrantLock = new ReentrantLock();
void buyTicket() {
String name = Thread.currentThread().getName();
try {
reentrantLock.lock();
System.out.println(name + ":准备好了");
Thread.sleep(100);
System.out.println(name + ":买好了");
reentrantLock.lock();
System.out.println(name + ":又准备好了");
Thread.sleep(100);
System.out.println(name + ":又买好了");
reentrantLock.lock();
System.out.println(name + ":准备好了");
Thread.sleep(100);
System.out.println(name + ":又买好了");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
}
public static void main(String[] args) {
final ReentrantLockTask task = new ReentrantLockTask();
Runnable runnable = new Runnable() {
@Override
public void run() {
task.buyTicket();
}
};
for (int i = 0; i < 10; i++) {
new Thread(runnable).start();
}
}
}
import java.util.concurrent.locks.ReentrantLock;
/**
* 演示 多个线程 去打印纸张,每个线程 打印张(ReentrantLock 公平锁,非公平锁)
*
* 公平锁:交易,比如先买票的人先进场
* 非公平锁:synchorinzed,场景比比皆是
*/
public class ReentrantLockDemo2 {
static class ReentrantLockTask {
ReentrantLock lock = new ReentrantLock(false
);
void print() {
String name = Thread.currentThread().getName();
try {
lock.lock();
//打印两次
System.out.println(name + "第一次打印");
Thread.sleep(1000);
lock.unlock();
lock.lock();
System.out.println(name + "第二次打印");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
final ReentrantLockTask task = new ReentrantLockTask();
Runnable runnable = new Runnable() {
@Override
public void run() {
task.print();
}
};
for (int i = 0; i < 10; i++) {
new Thread(runnable).start();
}
}
}
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* 我们演示 生产者与消费者的场景,利用的是ReentrantLock condition 条件对象,能够指定唤醒某个线程去工作
*
*
* 生产者是:一个boss 去生产砖,砖的序列号为偶数,那么工人2去搬,奇数号让工人去去搬
*
* 消费者是两个工人,有砖搬就搬,没转搬就休息
*/
public class ReentrantLockDemo3 {
static class ReentrantLockTask {
private Condition worker1Condition, worker2Condition;
ReentrantLock lock = new ReentrantLock(true);
volatile int flag = 0;//砖的序列号
public ReentrantLockTask() {
worker1Condition = lock.newCondition();
worker2Condition = lock.newCondition();
}
//工人1搬砖
void work1() {
try {
lock.lock();
if (flag == 0 || flag % 2 == 0) {
System.out.println("worker1 无砖可搬,休息会");
worker1Condition.await();
}
System.out.println("worker1 搬到的砖是:" + flag);
flag = 0;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//工人2搬砖
void work2() {
try {
lock.lock();
if (flag == 0 || flag % 2 != 0) {
System.out.println("worker2 无砖可搬,休息会");
worker2Condition.await();
}
System.out.println("worker2 搬到的砖是:" + flag);
flag = 0;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
void boss() {
try {
lock.lock();
flag = new Random().nextInt(100);
if (flag % 2 == 0) {
worker2Condition.signal();
System.out.println("生产出来了砖,唤醒工人2去搬:" + flag);
} else {
worker1Condition.signal();
System.out.println("生产出来了砖,唤醒工人1去搬:" + flag);
}
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
final ReentrantLockTask lockTask = new ReentrantLockTask();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
lockTask.work1();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
lockTask.work2();
}
}
}).start();
for (int i = 0; i < 10; i++) {
lockTask.boss();
}
}
}
}
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 利用ReentrantReadWriteLock 来实现 多人在线文档查看与编辑的功能
*/
public class ReentrantReadWriteLockDemo {
static class ReentrantReadWriteLockTask {
private final ReentrantReadWriteLock.ReadLock readLock;
private final ReentrantReadWriteLock.WriteLock writeLock;
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
ReentrantReadWriteLockTask() {
readLock = lock.readLock();
writeLock = lock.writeLock();
}
void read() {
String name = Thread.currentThread().getName();
try {
readLock.lock();
System.out.println("线程" + name + " 正在读取数据...");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
readLock.unlock();
System.out.println("线程" + name + " 释放了读锁...");
}
}
void write() {
String name = Thread.currentThread().getName();
try {
writeLock.lock();
System.out.println("线程" + name + " 正在写入数据...");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
writeLock.unlock();
System.out.println("线程" + name + " 释放了写锁...");
}
}
public static void main(String[] args) {
final ReentrantReadWriteLockTask task = new ReentrantReadWriteLockTask();
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
task.read();
}
}).start();
}
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
task.write();
}
}).start();
}
}
}
}
“ ” | 读锁 | 写锁 |
---|---|---|
读锁 | 可以访问 | 不可访问 |
写锁 | 不可访问 | 不可访问 |
import android.content.ContentValues.TAG
import android.os.Handler
import android.os.Looper
import androidx.annotation.IntRange
import java.util.concurrent.*
import java.util.concurrent.atomic.AtomicLong
import java.util.concurrent.locks.Condition
import java.util.concurrent.locks.ReentrantLock
import kotlin.math.max
/**
* 支持按任务的优先级去执行,
* 支持线程池暂停.恢复(批量文件下载,上传) ,
* 异步结果主动回调主线程
* todo 线程池能力监控,耗时任务检测,定时,延迟,
*/
object HiExecutor {
private const val TAG: String = "HiExecutor"
private var isPaused: Boolean = false
private var hiExecutor: ThreadPoolExecutor
private var lock: ReentrantLock = ReentrantLock()
private var pauseCondition: Condition
private val mainHandler = Handler(Looper.getMainLooper());
init {
pauseCondition = lock.newCondition()
val cpuCount = Runtime.getRuntime().availableProcessors()
val corePoolSize = cpuCount + 1
val maxPoolSize = cpuCount * 2 + 1
val blockingQueue: PriorityBlockingQueue<out Runnable> = PriorityBlockingQueue()
val keepAliveTime = 30L
val unit = TimeUnit.SECONDS
val seq = AtomicLong()
val threadFactory = ThreadFactory {
val thread = Thread(it)
//hi-executor-0
thread.name = "hi-executor-" + seq.getAndIncrement()
return@ThreadFactory thread
}
hiExecutor = object : ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveTime,
unit,
blockingQueue as BlockingQueue<Runnable>,
threadFactory
) {
override fun beforeExecute(t: Thread?, r: Runnable?) {
if (isPaused) {
lock.lock()
try {
pauseCondition.await()
} finally {
lock.unlock()
}
}
}
override fun afterExecute(r: Runnable?, t: Throwable?) {
//监控线程池耗时任务,线程创建数量,正在运行的数量
HiLog.e(TAG, "已执行完的任务的优先级是:" + (r as PriorityRunnable).priority)
}
}
}
fun execute(@IntRange(from = 0, to = 10) priority: Int = 0, runnable: Runnable) {
hiExecutor.execute(PriorityRunnable(priority, runnable))
}
abstract class Callable<T> : Runnable {
override fun run() {
mainHandler.post { onPrepare() }
val t: T? = onBackground()
//移除所有消息.防止需要执行onCompleted了,onPrepare还没被执行,那就不需要执行了
mainHandler.removeCallbacksAndMessages(null)
mainHandler.post { onCompleted(t) }
}
open fun onPrepare() {
//转菊花
}
abstract fun onBackground(): T?
abstract fun onCompleted(t: T?)
}
class PriorityRunnable(val priority: Int, private val runnable: Runnable) : Runnable,
Comparable<PriorityRunnable> {
override fun compareTo(other: PriorityRunnable): Int {
return if (this.priority < other.priority) 1 else if (this.priority > other.priority) -1 else 0
}
override fun run() {
runnable.run()
}
}
fun pause() {
lock.lock()
try {
isPaused = true
HiLog.e(TAG, "hiExecutor is paused")
} finally {
lock.unlock()
}
}
fun resume() {
lock.lock()
try {
isPaused = false
pauseCondition.signalAll()
} finally {
lock.unlock()
}
HiLog.e(TAG, "hiExecutor is resumed")
}
}
协程写法
协程的目的是为了让多个任务之间更好的协作,解决异步回调嵌套。能够以同步的方式编排代码完成异步工作。将异步代码像同步代码一样直观。同时它也是一个并发流程控制的解决方案。
协程主要是让原来使用“异步+回调”写出来的复杂代码,简化成看似同步写出来的方式,弱化了线程的概念(对线程的操作进一步抽象)。
import android.util.Log
import kotlinx.coroutines.*
object CoroutineScene {
private val TAG: String = "CoroutineScene"
/**
* 以此启动三个子线程, 并且同步的方式拿到他们的返回值,进而更新UI
*/
fun startScene1() {
GlobalScope.launch(Dispatchers.Unconfined) {
Log.e(TAG, "coroutine is running")
val result1 = request1()
val result2 = request2(result1)
val result3 = request3(result2)
updateUI(result3)
}
Log.e(TAG, "coroutine has launched")
}
/**
* 启动一个线程,先执行request1,完了之后,同时运行request2 和request3, 这俩并发都结束了才执行updateIU
*/
fun startScene2() {
GlobalScope.launch(Dispatchers.Main) {
Log.e(TAG, "coroutine is running")
val result1 = request1()
// request2()
// request3()
val deferred2 = GlobalScope.async { request2(result1) }
val deferred3 = GlobalScope.async { request3(result1) }
// deferred2.await();
//deferred3.await()
updateUI(deferred2.await(), deferred3.await())
}
Log.e(TAG, "coroutine has started")
}
private fun updateUI(result2: String, result3: String) {
Log.e(TAG, "updateui work on ${Thread.currentThread().name}")
Log.e(TAG, "paramter:" + result3 + "---" + result2)
}
private fun updateUI(result3: String) {
Log.e(TAG, "updateui work on ${Thread.currentThread().name}")
Log.e(TAG, "paramter:" + result3)
}
//suspend关键字的作用--->
//delay既然是IO异步任务,是如何做到延迟协程 中的代码向下执行的?
suspend fun request1(): String {
delay(2 * 1000) //不会暂停线程,但会暂停当前所在的协程
//Thread.sleep(2000) 让线程休眠
Log.e(TAG, "request1 work on ${Thread.currentThread().name}")
return "result from request1"
}
suspend fun request2(result1: String): String {
delay(2 * 1000)
Log.e(TAG, "request2 work on ${Thread.currentThread().name}")
return "result from request2"
}
suspend fun request3(result2: String): String {
delay(2 * 1000)
Log.e(TAG, "request3 work on ${Thread.currentThread().name}")
return "result from request3"
}
}
挂起函数
被关键字suspend修饰的方法在编译阶段,编译器会修改方法的签名,包括返回值,修饰符,入参,方法实体。协程的挂起是靠挂起函数中实现的代码。
协程挂起与协程恢复
实例代码
import android.util.Log
import kotlinx.coroutines.delay
object CoroutineScene2 {
private val TAG: String = "CoroutineScene2"
suspend fun request1(): String {
val request2 = request2();
return "result from request1 " + request2;
}
suspend fun request2(): String {
delay(2 * 1000)
Log.e(TAG, "request2 completed")
return "result from request2"
}
}
import android.util.Log;
import org.jetbrains.annotations.NotNull;
import kotlin.coroutines.Continuation;
import kotlin.coroutines.CoroutineContext;
import kotlin.coroutines.intrinsics.IntrinsicsKt;
import kotlinx.coroutines.DelayKt;
/**
* suspend fun request1(): String {
* val request2 = request2();
* return "result from request1 " + request2;
* }
*
*
* suspend fun request2(): String {
* delay(2 * 1000)
* Log.e(TAG, "request2 completed")
* return "result from request2"
* }
*/
public class CoroutineScene2_decompiled {
private static final String TAG = "CoroutineScene2";
public static final Object request1(Continuation preCallback) {
ContinuationImpl request1Callback;
if (!(preCallback instanceof ContinuationImpl) || (((ContinuationImpl) preCallback).label & Integer.MIN_VALUE) == 0) {
request1Callback = new ContinuationImpl(preCallback) {
@Override
Object invokeSuspend(@NotNull Object resumeResult) {
this.result = resumeResult;
this.label |= Integer.MIN_VALUE;
Log.e(TAG, "request1 has resumed");
return request1(this);
}
};
} else {
request1Callback = (ContinuationImpl) preCallback;
}
switch (request1Callback.label) {
case 0: {
// Object delay = DelayKt.delay(2000, request1Callback);
Object request2 = request2(request1Callback);
if (request2 == IntrinsicsKt.getCOROUTINE_SUSPENDED()) {
Log.e(TAG, "request1 has suspended");
return IntrinsicsKt.getCOROUTINE_SUSPENDED();
}
}
}
Log.e(TAG, "request1 completed");
return "result from request1" + request1Callback.result;
}
public static final Object request2(Continuation preCallback) {
ContinuationImpl request2Callback;
if (!(preCallback instanceof ContinuationImpl) || (((ContinuationImpl) preCallback).label & Integer.MIN_VALUE) == 0) {
request2Callback = new ContinuationImpl(preCallback) {
@Override
Object invokeSuspend(@NotNull Object resumeResult) {
this.result = resumeResult;
this.label |= Integer.MIN_VALUE;
Log.e(TAG, "request2 has resumed");
return request2(this);
}
};
} else {
request2Callback = (ContinuationImpl) preCallback;
}
switch (request2Callback.label) {
case 0: {
Object delay = DelayKt.delay(2000, request2Callback);
if (delay == IntrinsicsKt.getCOROUTINE_SUSPENDED()) {
Log.e(TAG, "request2 has suspended");
return IntrinsicsKt.getCOROUTINE_SUSPENDED();
}
}
}
Log.e(TAG, "request2 completed");
return "result from request2";
}
static abstract class ContinuationImpl<T> implements Continuation<T> {
private Continuation preCallback;
int label;
Object result;
public ContinuationImpl(Continuation preCallback) {
this.preCallback = preCallback;
}
@NotNull
@Override
public CoroutineContext getContext() {
return preCallback.getContext();
}
@Override
public void resumeWith(@NotNull Object resumeResult) {
Object suspend = invokeSuspend(resumeResult);
if (suspend == IntrinsicsKt.getCOROUTINE_SUSPENDED()) {
return;
}
preCallback.resumeWith(suspend);
}
abstract Object invokeSuspend(@NotNull Object resumeResult);
}
}
需求分析:如何让普通函数适配协程,成为“真正的挂起函数”。即让调用方以同步的方式拿到异步任务返回结果
import android.content.res.AssetManager
import android.util.Log
import kotlinx.coroutines.suspendCancellableCoroutine
import java.io.BufferedReader
import java.io.InputStreamReader
import java.lang.StringBuilder
/**
* 演示以异步的方式 读取 asstes目录下的文件,并且适配协程的写法,让他真正的挂起函数
*
* 方便调用方 直接以同步的形式拿到返回值
*/
object CoroutineScene3 {
suspend fun parseAssetsFile(assetManager: AssetManager, fileName: String): String {
// suspendCoroutine<> { }
return suspendCancellableCoroutine { continuation ->
Thread(Runnable {
val inputStream = assetManager.open(fileName)
val br = BufferedReader(InputStreamReader(inputStream))
var line: String?
var stringBuilder = StringBuilder()
// while ((line=br.readLine())!=null){
//
// }
do {
line = br.readLine()
if (line != null) stringBuilder.append(line) else break
} while (true)
inputStream.close()
br.close()
Thread.sleep(2000)
Log.e("coroutine", "parseassetsfile completed")
continuation.resumeWith(Result.success(stringBuilder.toString()))
}).start()
}
}
}
import java.util.Random;
import java.util.concurrent.CountDownLatch;
/**
* 演示一个 多人过山车的场景.
*
* 我们假设有5人 去乘坐做过山车,----等待5人全部准备好,才能发车
*/
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
final CountDownLatch downLatch = new CountDownLatch(5);
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(new Random().nextInt(4000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "准备好了");
downLatch.countDown();
}
}).start();
}
downLatch.await();
System.out.println("所有人都准备好了,准备发车...");
}
}
import java.util.Random;
import java.util.concurrent.Semaphore;
/**
* 演示 多人故宫游玩,但是同一时刻限流3人
*/
public class SemaphoreDemo {
public static void main(String[] args) {
final Semaphore semaphore = new Semaphore(3, true);
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
String name = Thread.currentThread().getName();
semaphore.acquire(2);
System.out.println(name + "获取到了许可证,进去游玩了");
Thread.sleep(new Random().nextInt(5000));
semaphore.release(2);
System.out.println(name + "归还了许可证");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
}