多线程 | 线程通信

1. while实现线程通信

//线程二需要while轮询 才能实现线程间通信,对cup消耗很大
//线程主动读取 而非对象等待/通知

        fun main(args: Array) {
            val goods = Goods()
            Thread(Runnable { goods.deduction(); Thread.sleep(300); goods.deduction(); }).start()
            Thread(Runnable {
                do {
                    Thread.sleep(200)
                } while (goods.stock > 3)
                println("商品库存减少到小于4")
            }).start()
        }

2. wait和Notify

  • 谁wait对谁上锁. 在调用wait()和notify()之前,线程必须获得该对象的对象级别锁,即只能在(该对象的)同步方法或同步代码块(该对象)中调用wait方法。
  • 每个对象的notify()只能唤醒一个wait().如果存在同一对象的多个wait()线程,则随机唤醒一个
  • wait()触发后,wait线程被挂起,等到该对象notify()方法触发,wait线程回到可运行状态,与其他线程公平竞争。notify()方法触发后,必须等到对象级别锁释放,也就是sychronized(obj)代码块执行完毕 ,wait线程才能被唤醒.
  • wait()触发,wait线程放弃对象锁并挂起该线程。
class WaN{
    private val lock = java.lang.Object()
    private val goods =Goods()
    fun dec(){
        synchronized(lock){
            for (i in 1..3) {
                goods.deduction()
            }
            lock.wait()
            //notify触发以后,线程被唤醒,但wait线程仍然要与其他线程公平竞争
            Thread.sleep(200)
            println("wait结束...")
        }
    }
    fun dis(){
        synchronized(lock){
            lock.notify()
            Thread.sleep(500)
            goods.discount()
//wait的对象级别锁 的notify执行到这里才算结束,也就是说,必须使wait的对象级别锁释放,wait线程才能从挂起状态被唤醒,
//而不是lock.notify行代码执行后,就立即唤醒wait线程
        }
    }
    companion object {
        @JvmStatic
        fun main(args: Array) {
            val WaN = WaN()
            Thread(Runnable { WaN.dec() }).start()
            Thread(Runnable { WaN.dec() }).start()
            Thread.sleep(2000)
            Thread(Runnable { WaN.dis() }).start()
        }
    }
}

3. 线程状态切换

线程切换示意图
  • 线程start()方法执行后,系统会为cpu分配资源,使其处于Runnable状态,这 是一个准备运行阶段,抢到cpu就是Running状态。
  • 从Running 到Runnable

每个锁对象都有两个队列:一个是就绪队列,一个是阻塞队列。就绪队列了将要获得锁的线程,阻塞队列存储了被阻塞的线程。

你可能感兴趣的:(多线程 | 线程通信)