同步屏障/协程/CyclicBarrier

1. 适用范围

在业务逻辑中有的时候会遇到一些等待多个子线程的返回结果再执行某个功能的情况,这种处理在代码上体现出来就不好阅读和维护,针对这一系列痛点建议java使用CyclicBarrier同步屏障,kotlin使用携程来处理,过程方便阅读,维护。

2. 场景

在正常使用情况下,如果事件放在子线程那么会出现,不确定时间,并行无法统一处理结果的问题如下图 ↓
yyyyy

我们理想中的流程应该是这样的,统一处理结果 ↓
yyyyy

CyclicBarrier

使用CyclicBarrier完成线程同步
yyyyy
yyyyy
yyyyy

4. GlobalScope

Kotlin使用协程完成线程同步(运行在子线程)
yyyyy
yyyyy
yyyyy

5. GlobalScope - withContext

Kotlin使用协程完成线程同步(运行在主线程)
yyyyy
yyyyy
yyyyy

代码

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.View
import android.widget.Button
import com.chenenyu.router.annotation.Route
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CyclicBarrier
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import android.os.Looper
import kotlinx.coroutines.*
import java.lang.Runnable


/**
 * @fileName: CyclicBarrierActivity
 * @date: 2019/9/9 19:07
 * @auther: YuanShuai
 * @tag: class//
 * @describe:
 **/
@Route("cyclicBarrier")
class CyclicBarrierActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_cyclicbarrier)
        findViewById<Button>(R.id.btn).apply {
            setOnClickListener {
                Log.e(
                    "CyclicBarrierActivity",
                    "(onCreate:${Thread.currentThread().stackTrace[2].lineNumber}) " +
                            "currentThread=" + isOnMainThread()
                )
                var cb = CyclicBarrier()
                cb.count()
            }

        }
        findViewById<Button>(R.id.btn2).apply {
            setOnClickListener {
                GlobalScope.launch {
                    Log.e(
                        "CyclicBarrierActivity",
                        "(onCreate:${Thread.currentThread().stackTrace[2].lineNumber})" +
                                "GlobalScope - isOnMainThread=" + isOnMainThread()
                    )
                    var i1 = thead1()
                    var i2 = thead2()
                    var i3 = thead3()
                    Log.e(
                        "CyclicBarrierActivity",
                        "(onCreate:${Thread.currentThread().stackTrace[2].lineNumber})" +
                                " 协程平均数=${(i1 + i2 + i3) / 3}"
                    )
                }
            }
        }
        findViewById<Button>(R.id.btn3).apply {
            setOnClickListener {
                GlobalScope.launch(Dispatchers.Main) {
                    Log.e(
                        "CyclicBarrierActivity",
                        "(onCreate:${Thread.currentThread().stackTrace[2].lineNumber})" +
                                "GlobalScope - isOnMainThread=" + isOnMainThread()
                    )
                    var number = 0
                    var number2 = 0
                    var number3 = 0
                    //当前线程是什么 这里面是什么线程  不需要suspend挂起方法
                    withContext(coroutineContext) {
                        Log.e(
                            "CyclicBarrierActivity",
                            "(onCreate:${Thread.currentThread().stackTrace[2].lineNumber})" +
                                    "GlobalScope - isOnMainThread=" + isOnMainThread()
                        )
                        number = mainThread()
                        number2 = mainThread2()
                        number3 = mainThread3()
                    }
                    Log.e(
                        "CyclicBarrierActivity",
                        "(onCreate:${Thread.currentThread().stackTrace[2].lineNumber})" +
                                "主线程协程平均数=${(number + number2 + number3) / 3}"
                    )
                }
            }
        }
    }

    fun mainThread(): Int {
        var num = (Math.random() * 40 + 60).toInt()
        Log.e(
            "CyclicBarrierActivity",
            "(mainThread:${Thread.currentThread().stackTrace[2].lineNumber}) num=$num"
        )
        return num
    }

    fun mainThread2(): Int {
        var num = (Math.random() * 40 + 60).toInt()
        Log.e(
            "CyclicBarrierActivity",
            "(mainThread:${Thread.currentThread().stackTrace[2].lineNumber}) num=$num"
        )
        return num
    }

    fun mainThread3(): Int {
        var num = (Math.random() * 40 + 60).toInt()
        Log.e(
            "CyclicBarrierActivity",
            "(mainThread:${Thread.currentThread().stackTrace[2].lineNumber}) num=$num"
        )
        return num
    }

    fun thead1(): Int {
        var n1 = (Math.random() * 40 + 60).toInt()
        Log.e(
            "CyclicBarrierActivity",
            "(thead1:${Thread.currentThread().stackTrace[2].lineNumber}) " +
                    "num=$n1"
        )
        return n1
    }

    suspend fun thead2(): Int {
        delay(2000)
        var n1 = (Math.random() * 40 + 60).toInt()
        Log.e(
            "CyclicBarrierActivity",
            "(thead1:${Thread.currentThread().stackTrace[2].lineNumber}) " +
                    "num=$n1"
        )
        return n1
    }

    suspend fun thead3(): Int {
        delay(5000)
        var n1 = (Math.random() * 40 + 60).toInt()
        Log.e(
            "CyclicBarrierActivity",
            "(thead1:${Thread.currentThread().stackTrace[2].lineNumber}) " +
                    "num=$n1"
        )
        return n1
    }


    private fun isOnMainThread(): Boolean {
        return Looper.myLooper() == Looper.getMainLooper()
    }

    class CyclicBarrier : Runnable {
        override fun run() {
            var result = 0
            var set: MutableSet<String> = map.keys
            for (s in set) {
                result += Integer.parseInt(map[s].toString())
            }
            Log.e(
                "CyclicBarrierActivity",
                "(run:${Thread.currentThread().stackTrace[2].lineNumber})" +
                        "   平均数为${result / 3}分"
            )
        }

        var threadPool: ExecutorService = Executors.newFixedThreadPool(3)
        var cb: java.util.concurrent.CyclicBarrier = CyclicBarrier(3, this)
        var map = HashMap<String, Int>()

        fun count() {
            threadPool.execute {
                var score = (Math.random() * 40 + 60).toInt()
                map[Thread.currentThread().name] = score
                Log.e(
                    "CyclicBarrierActivity",
                    "num=$score "
                )
                cb.await()
            }
            threadPool.execute {
                Thread.sleep(2000)
                var score = (Math.random() * 40 + 60).toInt()
                map[Thread.currentThread().name] = score
                Log.e(
                    "CyclicBarrierActivity",
                    "num=$score "
                )
                cb.await()
            }
            threadPool.execute {
                Thread.sleep(5000)
                var score = (Math.random() * 40 + 60).toInt()
                map[Thread.currentThread().name] = score
                Log.e(
                    "CyclicBarrierActivity",
                    "num=$score "
                )
                cb.await()
            }
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值