《Java 高并发》03 线程的生命周期

相关概念

进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。

一个进程是一个独立的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一个包含了不同的类和程序的单一进程。线程可以被称为轻量级进程。线程需要较少的资源来创建和驻留在进程中,并且可以共享进程中的资源。

多线程程序中,多个线程被并发的执行以提高程序的效率,CPU不会因为某个线程需要等待资源而进入空闲状态。多个线程共享堆内存(heap memory),因此创建多个线程去执行一些任务会比创建多个进程更好。举个例子,ServletsCGI 更好,是因为 Servlets 支持多线程而 CGI 不支持。

这里所谓的多个线程“同时”执行是人的感觉,实际上,是多个线程轮换执行。

线程调度器(Thread Scheduler)是一个操作系统服务,它负责为Runnable状态的线程分配CPU时间。一旦我们创建一个线程并启动它,它的执行便依赖于线程调度器的实现。

时间片(Time Slicing)是指将可用的CPU时间分配给可用的Runnable线程的过程。分配CPU时间可以基于线程优先级或者线程等待的时间。线程调度并不受到Java虚拟机控制,所以由应用程序来控制它是更好的选择(也就是说不要让你的程序依赖于线程的优先级)。

线程的生命周期(六种状态)

public enum State {NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED;
}
  • NEW:只存在于线程刚创建,未调用start之前。
MyThread myThread = new MyThread();System.out.println(myThread.getState());
  • RUNNABLE:正在 JVM 中执行,但是这个"执行",不一定是真的在运行, 也有可能是在等待CPU资源。所以,在网上,有人把这个状态区分为READYRUNNING两个,一个表示的start了,资源一到位随时可以执行,另一个表示真正的执行中,这取决于操作系统处理器。
MyThread myThread = new MyThread();myThread.start();System.out.println(myThread.getState());
  • BLOCKED:线程等待获取一个锁,来继续执行下一步的操作,比较经典的就是synchronized关键字,这个关键字修饰的代码块或者方法,均需要获取到对应的锁,在未获取之前,其线程的状态就一直未BLOCKED,如果线程长时间处于这种状态下,我们就要当心是否会出现死锁的情况。
public class MyThreadTest {public static void main(String[] args) throws InterruptedException {byte[] lock = new byte[0];MyThread thread1 = new MyThread(lock);thread1.start();MyThread thread2 = new MyThread(lock);thread2.start();Thread.sleep(1000);//等一会再检查状态System.out.println(thread2.getState());}}class MyThread extends Thread {private byte[] lock = new byte[0];public MyThread(byte[] lock) {this.lock = lock;}@Overridepublic void run() {synchronized (lock) {try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("done");}}
}
  • WAITING:等待状态。进入这个状态,一定是执行了如下的一些代码,例如

    • Object.wait()
    • Thread.join()
    • LockSupport.park()

    当一个线程执行了Object.wait()的时候,它一定在等待另一个线程执行Object.notify()或者Object.notifyAll()。或者一个线程thread,其在主线程中被执行了thread.join()的时候,主线程即会等待该线程执行完成。当一个线程执行了LockSupport.park()的时候,其在等待执行LockSupport.unpark(thread)。当该线程处于这种等待的时候,其状态即为WAITING。需要关注的是,这边的等待是没有时间限制的,当发现有这种状态的线程的时候,若其长时间处于这种状态,也需要关注下程序内部有无逻辑异常。

    LockSupport.park()

    public class MyThreadTest {public static void main(String[] args) throws InterruptedException {byte[] lock = new byte[0];MyThread thread1 = new MyThread(lock);thread1.start();Thread.sleep(100);System.out.println(thread1.getState());LockSupport.unpark(thread1);Thread.sleep(100);System.out.println(thread1.getState());}}class MyThread extends Thread {private byte[] lock = new byte[0];public MyThread(byte[] lock) {this.lock = lock;}@Overridepublic void run() {LockSupport.park();}
    }

    Object.wait()

    public class MyThreadTest {public static void main(String[] args) throws InterruptedException {byte[] lock = new byte[0];MyThread thread1 = new MyThread(lock);thread1.start();Thread.sleep(100);System.out.println(thread1.getState()); //这时候线程状态应为WAITINGsynchronized (lock){lock.notify(); //notify通知wait的线程}Thread.sleep(100);System.out.println(thread1.getState());}}class MyThread extends Thread {private byte[] lock = new byte[0];public MyThread(byte[] lock) {this.lock = lock;}@Overridepublic void run() {synchronized (lock){try {lock.wait(); //wait并允许其他线程同步lock} catch (InterruptedException e) {e.printStackTrace();}}}
    }

    Thread.join()

    public class MyThreadTest {public static void main(String[] args) throws InterruptedException {byte[] lock = new byte[0];MyThread1 thread1 = new MyThread1(lock);thread1.start();MyThread2 thread2 = new MyThread2(thread1);thread2.start();Thread.sleep(100);System.out.println(thread2.getState());}}class MyThread1 extends Thread {private byte[] lock = new byte[0];public MyThread1(byte[] lock) {this.lock = lock;}@Overridepublic void run() {try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}}
    }class MyThread2 extends Thread {Thread thread;public MyThread2(Thread thread) {this.thread = thread;}@Overridepublic void run() {try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}}
    }
  • TIMED_WAITING:这个状态和WAITING状态的区别就是,这个状态的等待是有一定时效的,即可以理解为WAITING状态等待的时间是永久的,即必须等到某个条件符合才能继续往下走,否则线程不会被唤醒。但是TIMED_WAITING,等待一段时间之后,会唤醒线程去重新获取锁。当执行如下代码的时候,对应的线程会进入到TIMED_WAITING状态。

    • Thread.sleep(long)
    • Object.wait(long)
    • Thread.join(long)
    • LockSupport.parkNanos()
    • LockSupport.parkUntil()
  • TERMINATED:这个状态很好理解,即为线程执行结束之后的状态

线程的状态图

 

image-20200814160913095

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/273595.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring boot 整合dynamic实现多数据源

项目git地址:Jacob-dynamic 准备工作 # 创建数据库db1 CREATE DATABASE db1CHARACTER SET utf8 COLLATE utf8_bin # 创建user表 CREATE TABLE user (id int(11) DEFAULT NULL,name varchar(255) DEFAULT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8 # 添加数据 INSERT…

Could not autowire. No beans of 'JavaMailSender' type found..md

Could not autowire. No beans of JavaMailSender type found. 导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId><version>2.1.5.RELEASE</version> </depe…

极客Web前端开发资源集锦

本周我们带来的前端推荐包含当前热门的bootstrap&#xff0c;html5&#xff0c;css3等技术内容和新闻话题&#xff0c;如果你还想近一步学习如何开发&#xff0c;还可以关注我们的极客课程库&#xff0c;里面涵盖了现代开发技术的‘学’与‘习’的全新功能。希望对大家有所帮助…

使用 Spring Cloud 实现微服务系统

使用 Spring Cloud 实现微服务系统 准备工作&#xff1a;为了方便创建项目&#xff0c;以及各版本以来关系&#xff0c;此次创建项目使用 Spring Assistant插件。 创建单体服务中心项目 启用服务端的服务注册&#xff0c;发现功能 EnableEurekaServer SpringBootApplication pu…

android 小工具:pc 上用 curl 命令打开手机浏览器,浏览指定网址

测试 API 时或其它情况经常需要在手机浏览器中输入 url 一长串的 url 输起来真是麻烦 AirDroid 很强大也不用数据线&#xff0c;但有时老断开连接&#xff0c;不是很爽。发到手机 qq 吧还得手动粘贴 所以自己开发了一个小工具 pc 上用 curl 发一条命令&#xff0c;命令中输入要…

iOS: How To Make AutoLayout Work On A ScrollView

转载自&#xff1a; http://natashatherobot.com/ios-autolayout-scrollview/ Posted on June 11th, 2014 Ok, I’ll admit. I’ve been seriously struggling with AutoLayout ever since it’s been introduced. I understand the concept, and I LOVE the idea of it, but w…

windows 中搭建Zookeeper的搭建

个人博客 &#xff1a;https://www.siyuan.run CSDN&#xff1a;https://blog.csdn.net/siyuan 微信小程序&#xff1a;思远Y 下载 下载地址&#xff1a; https://mirrors.cnnic.cn/apache/zookeeper/ PS&#xff1a;zookeeper 从3.5.5以后的版本带有bin标识的包&#xff0c;否…

Vs Code:Remote SSH

Remote SSH 简介 Remote - SSH 扩展允许您使用任何带有 SSH 服务器的远程计算机作为开发环境。由于几乎每个桌面和服务器操作系统都有可配置的 SSH 服务器&#xff0c;因此该扩展可以在各种情况下大大简化开发。 您可以&#xff1a; 在部署的同一操作系统上进行开发&#xff…

样条之贝塞尔(Bezier)

我曾经发过两篇关于贝塞尔的文章&#xff1a;数学图形(1.47)贝塞尔(Bzier)曲线&#xff0c;数学图形之贝塞尔(Bzier)曲面。那是使用我自己定义的脚本语言生成贝塞尔图形。由于我自己定义的脚本语法功能有限&#xff0c;所以最多只能支持5次贝塞尔函数&#xff0c;而这里将实现N…

设计模式 之 工厂模式

项目源码&#xff1a;https://gitee.com/Jacob-gitee/DesignMode 个人博客&#xff1a;https://jacob.org.cn 女娲造人的故事 东汉《风俗通》记录了一则神话故事&#xff1a;“开天辟地&#xff0c;未有人民&#xff0c;女娲搏黄土做人”&#xff0c;讲述的内容就是大家非常熟…

设计模式 之 单例模式

项目源码&#xff1a;https://gitee.com/Jacob-gitee/DesignMode 个人博客&#xff1a;https://jacob.org.cn 宗旨 Ensure a class has only one instance,and provide a global point of access to it.&#xff08;确保某一个类只有一个实例&#xff0c;而且自行实例化并向整个…

设计模式 之 抽象工厂模式

项目源码&#xff1a;https://gitee.com/Jacob-gitee/DesignMode 个人博客 &#xff1a;https://jacob.org.cn 女娲的失误 工厂模式中讲了女娲造人的故事。人是造出来了&#xff0c;世界也热闹了&#xff0c;可是低头一看&#xff0c;都是清一色的类型&#xff0c;缺少关爱、仇…

设计模式 之 模板模式

项目源码&#xff1a;https://gitee.com/Jacob-gitee/DesignMode 个人博客 &#xff1a;http://jacob.org.cn 女娲的失误 工厂模式中讲了女娲造人的故事。人是造出来了&#xff0c;世界也热闹了&#xff0c;可是低头一看&#xff0c;都是清一色的类型&#xff0c;缺少关爱、仇…

使用Java高速实现进度条

基于有人问到如何做进度条&#xff0c;以下给个简单的做法&#xff1a; 主要是使用JProgressBar&#xff08;Swing内置javax.swing.JProgressBar&#xff09;和SwingWorker&#xff08;Swing内置javax.swing.SwingWorker&#xff09; 有人肯定会说&#xff0c;不是用线程做的吗…

关于js的function.来自百度知道的回答,学习了.

在js中&#xff0c;创建一个函数对象的语法是var myFunction new Function(arg1,…,agrN, body);其中&#xff0c;该函数对象的N个参数放在 函数主体参数body的前面&#xff0c;即函数主体参数必须放在参数列表的最后&#xff0c;也可以无参数new Function(body)。你添加第三个…

fedora20开机启动配置:systemctl

老版fedora中使用chkconfig配置开机启动&#xff0c;fedora20中&#xff0c;使用chkconfig会出现各种问题。使用systemctl配置。 具体表格如下 转载于:https://www.cnblogs.com/hh6plus/p/5548083.html

《Java 高并发》01 高并发基本概念

基本概念 同步和异步 同步和异步通常是用来形容一次方法调用。 同步方法调用一旦开始&#xff0c;调用者必须等到方法返回才能继续执行后续操作。 异步方法调用更像一个消息传递&#xff0c;一旦开始&#xff0c;方法调用就会立即返回&#xff0c;调用者就可以继续后续的操…

Android之Http网络编程(四)

前面几篇博文简单的介绍了一些常见的Http的操作&#xff0c;这些操作几乎都是在新开的线程中进行的网络请求&#xff0c;并在日志中打印出获取到的网络数据。那么&#xff0c;问题来了&#xff01;&#xff08;呃~感觉下一句是蓝翔有木有&#xff1f;&#xff09;如何在把获取到…

mybatis 2 -常用数据操作

1、写入数据并获取自增ID XML配置&#xff1a; <!-- 写入数据获取自增ID --><insert id"insertLog" parameterType"com.mamaguwen.entity.sys_loginlog" useGeneratedKeys"true" keyProperty"logid">insert into sys_…

Docker 搭建 ELK 日志系统,并通过 Kibana 查看日志

Docker 搭建 ELK 日志系统,并通过 Kibana 查看日志 docker-compose.yml version: 3 services:elasticsearch:image: elasticsearch:7.7.0 #镜像container_name: elasticsearch #定义容器名称restart: always #开机启动&#xff0c;失败也会一直重启environment:- "cl…