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)

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

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Laoqi's Linux运维专列

Linux入门到精pao通lu

40250
来自专栏散尽浮华

nginx负载均衡(5种方式)、rewrite重写规则及多server反代配置梳理

Nginx除了可以用作web服务器外,他还可以用来做高性能的反向代理服务器,它能提供稳定高效的负载均衡解决方案。nginx可以用轮询、IP哈希、URL哈希等方式...

82260
来自专栏Android-薛之涛

Android-多线程

        通俗的说:我们平日里打开的QQ,微信,简书,都是一个进程。进程是程序的一次动态执行过程,它需要经历从代码加载,代码执行到执行完毕的一个完整的过程...

10620
来自专栏黑泽君的专栏

用gcc编译c语言程序以及其编译过程

对于初学c语言编程的我们来说,学会如何使用gcc编译器工具,对理解c语言的执行过程,加深对c语言的理解很重要!!!

17010
来自专栏机器学习算法与Python学习

python: import详解

在python用import或者from...import或者from...import...as...来导入相应的模块,作用和使用方法与C语言的include...

33360
来自专栏cs

python多线程知识点

Thread是线程类,有两种使用方法,直接传入要运行的方法或从Thread继承并覆盖run(): 构造方法: Thread(group=None, targ...

10920
来自专栏王二麻子IT技术交流园地

Linux常用命令100个用法

平时用linux时,我有一个习惯就是把遇到的,比较有用,并且容易忘的命令,放到一个文本文件中,没事的时候可以拿出来看看,这样可以加深映像,时间长了这些命令的用法...

25050
来自专栏我是攻城师

elasticsearch的查询流程分析

52160
来自专栏Petrichor的专栏

pycharm: 跳转 & 回退

26820
来自专栏python3

python3--中的进程操作--multiprocess模块

运行中的程序就是一个进程。所有的进程都是通过它的父进程来创建的。因此,运行起来的python程序也是一个进程,那么我们也可以在程序中再创建进程。多个进程可以实现...

12210

扫码关注云+社区

领取腾讯云代金券