美文网首页
java多线程学习 2

java多线程学习 2

作者: fdsun | 来源:发表于2020-09-04 16:17 被阅读0次

    java多线程2

    生命周期,线程通讯
    

    一、生命周期

    初始状态(new)
    就绪 -- 运行 -- 阻塞
    死亡
    
    __/\__
    

    1、yield()方法

    yield()让当前正在运行的线程回到就绪,以允许具有相同优先级的其他线程获得运行的机会。但是,实际中无法保证yield()达到让步的目的,因为,让步的线程可能被线程调度程序再次选中。
    同时yield()不会放弃锁资源,所以有可能会出现死锁。

    2、wait和sleep方法的区别

    1)第一个很重要的区别就是,wait方法必须正在同步环境下使用,比如synchronized方法或者同步代码块。如果你不在同步条件下使用,会抛出IllegalMonitorStateException异常。另外,sleep方法不需要再同步条件下调用,你可以任意正常的使用。
    2)第二个区别是,wait方法用于和定义于Object类的,而sleep方法操作于当前线程,定义在java.lang.Thread类里面。
    3)第三个区别是,调用wait()的时候方法会释放当前持有的锁,而sleep方法不会释放任何锁。

    3、wait和sleep方法使用场景

    1)wait方法定义在Object类里面,所有对象都能用到,一般wait()和notify()方法或notifyAll使用于线程间的通信。
    2)sleep()方法用于暂停当前线程的执行。

    4、join方法()

    thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。
    比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

    5、stop方法

    线程启动完毕后,在运行可能需要终止,Java提供的终止方法只有一个stop,但是不建议使用此方法,因为它有以下三个问题:
    1)stop方法是过时的。
    从Java编码规则来说,已经过时的方式不建议采用.
    2)stop方法会导致代码逻辑不完整
    stop方法是一种"恶意" 的中断,一旦执行stop方法,即终止当前正在运行的线程,不管线程逻辑是否完整,这是非常危险的.
    3)stop方法会破坏原子逻辑
    多线程为了解决共享资源抢占的问题,使用了锁的概念,避免资源不同步,但是正是因为此原因,stop方法却会带来更大的麻烦,它会丢弃所有的锁,导致原子逻辑受损

    二、线程通讯小案例

    1、如何让两个线程依次执行?

    题目:假设有两个线程,一个是线程 A,另一个是线程 B,两个线程分别依次打印 1-3 三个数字即可。我们希望 B 在 A 全部打印完后再开始打印。

    关键方法:join()

    2、如何让两个线程按照指定方式有序交叉运行呢?

    题目:假设有两个线程,一个是线程 A,另一个是线程 B,两个线程分别依次打印 1-3 三个数字即可。我们希望 A和B交替打印

    关键方法:wait()和notify()或者notifyAll()

    3、四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的。

    关键对象:CountdownLatch对象

    ​ 最开始我们介绍了 thread.join(),可以让一个线程等另一个线程运行完毕后再继续执行,那我们可以在 D 线程里依次 join A B C,不过这也就使得 A B C 必须依次执行,而我们要的是这三者能同步运行。
    或者说,我们希望达到的目的是:A B C 三个线程同时运行,各自独立运行完后通知 D;对 D 而言,只要 A B C 都运行完了,D 再开始运行。针对这种情况,我们可以利用 CountdownLatch 来实现这类通信方式。

    4、三个运动员各自准备,等到三个人都准备好后,再一起跑

    关键对象:CyclicBarrier

    上面的 CountDownLatch 可以用来倒计数,但当计数完毕,只有一个线程的 await() 会得到响应,无法让多个线程同时触发。

    为了实现线程间互相等待这种需求,我们可以利用 CyclicBarrier 数据结构。

    5、子线程完成某件任务后,把得到的结果回传给主线程

    关键接口:Callable

    tips:通过 FutureTask 和 Callable 可以直接在主线程获得子线程的运算结果,只不过需要阻塞主线程。当然,如果不希望阻塞主线程,可以考虑利用 ExecutorService,把 FutureTask 放到线程池去管理执行。

    相关文章

      网友评论

          本文标题:java多线程学习 2

          本文链接:https://www.haomeiwen.com/subject/wqazsktx.html