专栏首页LuckQIJava多线程总结三

Java多线程总结三

前面的两篇文章简单的介绍了下关于线程有关Api的介绍和锁的应用,这些都是我们在开发中经常用到的方法和手段。多多练习,我们就会掌握住,虽然我们了解了API的使用,但是只懂表面,不深入了解,对于作为开发的我们来说,不能止于表面。让我们现在开始深入底部看看多线程是怎么运行的吧。

线程的状态

在线程中一般分为七种状态。但是其中等待阻塞睡眠可以当成一种状态

  1. New :新建立的线程,线程对象创建完毕,但是还没调用start方法,或者没有放到线程池里面提交
  2. Running : 运行状态,获得线程需要的资源,这是线程进入运行的唯一状态
  3. Terminated : 线程死亡阶段,当线程运行完毕后状态。死亡后不可操作
  4. Timed_waiting : 睡眠状态,指定睡眠多长时间的操作,可相当于暂停。
  5. Blocked :阻塞状态,没有获得资源或者锁资源。处于待执行的状态
  6. Waiting : 等待状态,获得唤醒之后继续操作。
  7. Ready : 准备阶段,执行了start方法,或者提交到线程池中,也可从其他状态转为该阶段

从下面的线程运行图可以看出整个线程运行的流程。具体其中的方法可以看[java多线程集合文章列表]

线程之间的通信机制

线程在整体运行中只是一个单独的个体,那么如果我们有很多个线程,那么他们之间的线程通信就是一种十分重要的手段。我们Java是怎么样实现线程之间的通信的呢?

等待与通信机制

等待通信机制,我们在程序中执行wait()与notity()方法来实现的。线程处于等待的时候,我们需要 用通知的方式来告知线程可以获取资源继续执行。

//  两个独立的线程 一个用来等待,一个用来通知。 就可以实现等待通知通信机制。
    lock.wait(); 
    lock.notify();   //只能通知一个线程 来唤醒 ,但是该方法具有随机性的唤醒。不能一对一的指定 如果想一对一的唤醒可以选择Lock的Condition 来实现。
    lock.notifyAll();  // 通知所有的等待线程

join 的使用

我们在程序中会在主程序中创建多个子程序,但是有时候主程序需要获取子程序中的执行结果,会需要等待子程序执行完成后才能获取。这样我们就可以用到join().该方法就是用来等待线程对象销毁,实际上内部使用的wait方法。

Thread thread  = new Thread();
     thread.join();
 // join 原理实现
 public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);  // 使用 wait来帮助 实现等待 无限循环
                now = System.currentTimeMillis() - base;
            }
        }
    }

但是在使用join 可能会出现的是主线程执行的代码在join后面的代码提前执行了。我们本来是让其等待子线程执行完毕再执行,可还是出现后面的代码提前执行的情况。

这是因为join在获取锁资源时,发现锁资源获取的时间已经超时,就会自动的把锁进行释放,那么所代表的是wait方法,wait方法在执行之后,会把锁资源进行释放,当再次获得锁资源之后超时在进行释放。在其他方面进行同样操作的线程也会同步输出。导致的。

本文分享自微信公众号 - LuckQI(YoungRUIQ),作者:super~琪琪

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-05-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java多线程技术总结

    用户2196435
  • java多线程技术总结

    用户2196435
  • 学习Java基础知识,打通面试关~十五线程池学习

    用户2196435
  • 如何控制nodejs的线程数

    nodejs提供了线程能力,但是我们不能一味地开启线程,需要控制数据,本文分享如何去控制数量。

    theanarkh
  • Java并发编程笔记——J.U.C之executors框架:executors框架设计理念

    juc-executors框架是整个J.U.C包中类/接口关系最复杂的框架,真正理解executors框架的前提是理清楚各个模块之间的关系,高屋建瓴,从整体到局...

    须臾之余
  • Android 多线程实现方式

    通常来说,一个应用至少有一个进程,而一个进程至少有一个线程。 线程是 CPU 调度的基本单位,进程是系统资源分配的基本单位。

    字节流动
  • Spring Boot使用@Async实现异步调用:自定义线程池

    在之前的Spring Boot基础教程系列中,已经通过《Spring Boot中使用@Async实现异步调用》一文介绍过如何使用 @Async注解来实现异步调用...

    程序猿DD
  • 基于线程与基于事件的并发编程之争

    你应当尽可能地避免线程,对于GUI和分布式系统或低端服务器不要用线程,只有处理CPU并发时才需要线程,如果必须使用线程,将线程隔离在核心内部,让...

    物流IT圈
  • C++多线程-优先级反转

    优先级反转对于编写应用层的人员来说不大会发生,但是对于操作系统的设计者来说确是一个逃不过去的问题。要知道怎么样处理优先级反转?那么先看看它是怎么发生的。

    cwl_java
  • 并发的核心:CAS 是什么?Java8是如何优化 CAS 的?

    大家可能都听说说 Java 中的并发包,如果想要读懂 Java 中的并发包,其核心就是要先读懂 CAS 机制,因为 CAS 可以说是并发包的底层实现原理。

    猿天地

扫码关注云+社区

领取腾讯云代金券