一、多线程概述

1.1、程序、进程、线程概念

1)程序

是为完成特定任务,用某种语言编写的一组指令的集合,即指一段静态的代码,静态对象

2)进程

是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。

3)线程

进程内部的一个独立执行单元;一个进程可以同时并发的运行多个线程,可以理解为一个进程便相当于一个单 CPU 操作系统,而线程便是这个系统中运行的多个任务。

1.2、并行与并发

1)并行

多个CPU同时执行多个任务;指两个或多个时间在同一时刻发生(同时发生)。

比如:多个人同时做不同的事

2)并发

一个CPU(采用时间片)同时执行多个任务,指两个或多个事件在一个时间段内发生。

比如秒杀平台,多个人做同件事

在操作系统中,安装了多个程序,并发指的是在一段时间内宏观上有多个程序同时运行,这在单 CPU 系统中,每一时刻只能有一道程序执行,即微观上这些程序是分时的交替运行,只不过是给人的感觉是同时运行,那是因为分时交替运行的时间是非常短的

而在多个 CPU 系统中,则这些可以并发执行的程序便可以分配到多个处理器上(CPU),实现多任务并行执行,即利用每个处理器来处理一个可以并发执行的程序,这样多个程序便可以同时执行

目前电脑市场上说的多核 CPU,便是多核处理器,核 越多,并行处理的程序越多,能大大的提高电脑运行的效率。

注意:单核处理器的计算机肯定不能并行的处理多个任务,只能是多个任务交替的在单个 CPU 上运行

1.3、多线程的作用

1)为了更好的利用cpu的资源,如果只有一个线程,则第二个任务必须等到第一个任务结束后才能进行,如果使用多线程则在主线程执行任务的同时可以执行其他任务,而不需要等待;

2)进程之间不能共享数据,线程可以;

3)系统创建进程需要为该进程重新分配系统资源,创建线程代价比较小;

4) Java语言内置了多线程功能支持,简化了java多线程编程。

1.4、进程与线程的区别

进程:有独立的内存空间,进程中的数据存放空间(堆空间和栈空间)是独立的,至少有一个线程。

线程:堆空间是共享的,栈空间是独立的,线程消耗的资源比进程小的多。

注意:

1)因为一个进程中的多个线程是并发运行的,那么从微观角度看也是有先后顺序的,哪个线程执行完全取决于 CPU 的调度,程序员是干涉不了的。而这也就造成的多线程的随机性。

2)Java 程序的进程里面至少包含两个线程,主进程也就是 main()方法线程,另外一个是垃圾回收机制线程。每当使用 java 命令执行一个类时,实际上都会启动一个 JVM,每一个 JVM 实际上就是在操作系统中启动了一个线程,java 本身具备了垃圾的收集机制,所以在 Java 运行时至少会启动两个线程。

3)由于创建一个线程的开销比创建一个进程的开销小的多,那么我们在开发多任务运行的时候,通常考虑创建多线程,而不是创建多进程。

二、线程的生命周期

1.1、线程生命周期图

1)线程状态图

2)线程状态转换图

3)具体运行转换图

1.2、线程生命周期详解

1.2.1、新建状态(New)

用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态。处于新生状态的线程有自己的内存空间。

备注:不能对已经启动的线程再次调用start()方法,否则会出现Java.lang.IllegalThreadStateException异常。

1.2.2、就绪状态(Runnable)

线程对象创建后,其他线程调用了该对象的start()方法时进入就绪状态。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

详解:

处于就绪状态的线程已经具备了运行条件,但还没有分配到CPU,处于线程就绪队列(尽管是采用队列形式,事实上,把它称为可运行池而不是可运行队列。因为cpu的调度不一定是按照先进先出的顺序来调度的),等待系统为其分配CPU。等待状态并不是执行状态,当系统选定一个等待执行的Thread对象后,它就会从等待执行状态进入执行状态,系统挑选的动作称之为“cpu调度”。一旦获得CPU,线程就进入运行状态并自动调用自己的run方法。

备注:如果希望子线程调用start()方法后立即执行,可以使用Thread.sleep()方式使主线程睡眠一伙儿,转去执行子线程。

1.2.3、运行状态(Running)

就绪状态的线程获取了CPU,执行程序代码。

详解:

处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态

处于就绪状态的线程,如果获得了cpu的调度,就会从就绪状态变为运行状态,执行run()方法中的任务。如果该线程失去了cpu资源,就会又从运行状态变为就绪状态。重新等待系统分配资源。也可以对在运行状态的线程调用yield()方法,它就会让出cpu资源,再次变为就绪状态。

1.2.4、阻塞状态(Blocked)

阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。

详解:

处于运行状态的线程在某些情况下,如执行了sleep(睡眠)方法,或等待I/O设备等资源,将让出CPU并暂时停止自己的运行,进入阻塞状态。

在阻塞状态的线程不能进入就绪队列。只有当引起阻塞的原因消除时,如睡眠时间已到,或等待的I/O设备空闲下来,线程便转入就绪状态,重新到就绪队列中排队等待,被系统选中后从原来停止的位置开始继续运行。

阻塞的情况分类:

​ 1)等待阻塞:运行的线程执行 wait()方法,JVM会把该线程放入等待池中。(wait会释放持有的锁)

​ 2)同步阻塞:运行的线程在获取对象的 同步锁 时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。

​ 3)其他阻塞:运行的线程执行 sleep()或join()方法 ,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超 时、或者I/O处理完毕时,线程重新转入就绪状态。(注意,sleep是不会释放持有的锁)

1.2.5、死亡状态(Dead)

线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

当线程的run()方法执行完,或者被强制性地终止,例如出现异常,或者调用了stop()、desyory()方法等等,就会从运行状态转变为死亡状态。

详解:

当线程的run()方法执行完,或者被强制性地终止,就认为它死去。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦死亡,就不能复生。 如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。

三、从JVM内存结构中看线程

1)Java虚拟机内存结构图

2)解释

程序(一段静态的代码)——————》加载到内存中——————》进程(加载到内存中的代码,动态的程序)

进程可细分为多个线程,一个线程代表一个程序内部的一条执行路径

每个线程有其独立的程序计数器(PC,指导着程序向下执行)与运行栈(本地变量等,本地方法等)

3)线程的分类

java中的线程分为两类:1.守护线程(如垃圾回收线程,异常处理线程),2.用户线程(如主线程)

若JVM中都是守护线程,当前JVM将退出。

四、线程开销

多线程中两个必要的开销:线程的创建、上下文切换

4.1、创建线程开销

创建线程使用是直接向系统申请资源的,对操作系统来说,创建一个线程的代价是十分昂贵的, 需要给它分配内存、列入调度,同时在线程切换的时候还要执行内存换页,CPU 的缓存被 清空,切换回来的时候还要重新从内存中读取信息,破坏了数据的局部性。

关于资源:Java线程的线程栈所占用的内存是在Java堆外的,所以是不受java程序控制的,只受系统资源限制,默认一个线程的线程栈大小是1M(当然这个可以通过设置-Xss属性设置,但是要注意栈溢出问题),但是,如果每个用户请求都新建线程的话,1024个用户光线程就占用了1个G的内存,如果系统比较大的话,一下子系统资源就不够用了,最后程序就崩溃了。

同样的道理在java程序中也不要随意开启新的线程,特别是高频业务尽量使用线程池,不然很容易导致内存不足,程序崩溃的问题

4.2、上下文切换开销

1.概念

当前任务执行一个时间片后会切换到下一个任务。在切换之前,上一个任务的状态会被保存下来,下次切换回这个任务时,可以再加载这个任务的状态,任务从保存到再加载的过程就是一次上下文切换。

2.说明

1)时间片是CPU分配给各个线程的时间,时间片一般是几十毫秒。

2)CPU通过给每个线程分配CPU时间片,并且不停地切换线程来实现多线程。因为时间片非常短,所以感觉多个线程是在同时执行。

3.减少上下文切换的方法

1)无锁并发编程

多线程竞争锁时,会引起上下文切换,所以在使用多线程处理数据时,可以采用一些策略来避免使用锁。

常见的策略:将数据按照id的哈希值进行切分,不同的线程处理不同段的数据。

2)锁分离技术

举例:ConcurrentHashMap

3)CAS算法

java的Atomic包使用CAS算法来更新数据,而不需要加锁。

4)使用最少的线程

避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这样会造成大量线程都处于等待状态。

举例:

通过减少大量WAITING的线程,来减少上下文切换次数

转储堆栈信息

jstack PID > dumpfile

统计所有线程的状态

grep java.lang.Thread.State dumpfile | awk '{print $2" "$3" "$4" "$5}' | sort | uniq -c

如果存在大量waiting的线程,则查看dumpfile文件进行分析:

1)如果是服务器的工作线程大量等待,则修改服务器配置文件中线程池的配置信息,然后重启查看效果。

初识Java多线程的更多相关文章

  1. 初识Java多线程编程

    Java 多线程编程 Java给多线程编程提供了内置的支持.一个多线程程序包含两个或多个能并发运行的部分.程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径. 多线程是多任务的一种特别 ...

  2. 初识Java

    Java是一种简单的.面向对象的.分布式的.解释的.安全的.可移植的.性能优异的多线程语言.它以极强的安全性.平台无关性.硬件结构无关性.语言简洁.面向对象的特点,在网络编程语言中占据了无可比拟的优势 ...

  3. Java 面向对象编程——第一章 初识Java

      第一章    初识Java 1.  什么是Java? Java是一种简单的.面向对象的.分布式的.解释的.安全的.可移植的.性能优异的多线程语言.它以其强安全性.平台无关性.硬件结构无关性.语言简 ...

  4. Java多线程编程总结一:多线程基本概念

    Java多线程编程总结一 – 初识多线程 进程.多进程.线程.多线程的概念 进程(process):CPU的执行路径.通俗的说就是系统中正在运行的程序.比如我们打开了浏览器.QQ等等,这些程序一旦被打 ...

  5. Java入门——初识Java

    Java入门——初识Java 摘要:本文主要对Java这门编程语言进行简单的介绍. Java简介 说明 Java语言历时十多年,已发展成为人类计算机史上影响深远的编程语言,从某种程度上来看,它甚至超出 ...

  6. JAVA:初识Java · Xer97

    1. 什么是Java Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,因此Java语言具有功能强大和简单易用两个特征. Java语言作为静 ...

  7. 40个Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...

  8. Java多线程基础知识篇

    这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...

  9. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

随机推荐

  1. 获取txt编码方式

    在操作txt的时候,有时会出现乱码,这是因为没有使用正确的编码方式来操作txt,我们需要先获取txt的编码方式,再进行读写操作.下面是获取txt编码的方法: /// <summary> / ...

  2. 字节笔试题 leetcode 69. x 的平方根

    更多精彩文章请关注公众号:TanLiuYi00 题目 解题思路 题目要求非负整数 x 的平方根,相当于求函数 y = √x 中 y 的值. 函数 y = √x  图像如下: 从上图中,可以看出函数是单 ...

  3. hdu 4497 GCD and LCM (非原创)

    GCD and LCM Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total ...

  4. 使用MCSManager搭建Minecraft服务器

    目录 一.准备工作 1.MCSManager Windows环境下安装 Linux安装 2.Minecraft服务端 3.Java 二.配置 1.登录面板 2.上传服务端 3.服务端的配置 三.开启服 ...

  5. Web API 设计

    Web API 设计 The Design of Web APIs free online ebook https://www.manning.com/books/the-design-of-web- ...

  6. GreenSock & SVG Animation

    GreenSock & SVG Animation refs https://greensock.com/ https://greensock.com/learning/ GSAP https ...

  7. TypeScript 面试题汇总(2020 版)

    TypeScript 面试题汇总(2020 版) TypeScript 3.9 https://www.typescriptlang.org/zh/ TypeScript 4.0 RC https:/ ...

  8. JavaScript Number Type Checker

    JavaScript Number Type Checker Number.isInteger // static 方法 Number.isInteger(value) https://develop ...

  9. leetcode solution cracked tutorial

    leetcode solution cracked tutorial problemset https://leetcode.com/problemset/all/ Top Interview Que ...

  10. css3 units & 1 turn

    css3 units & 1 turn One full circle is 1turn, 180deg === 0.5turn degrees, gradians, radians, tur ...