一、进程与线程

(1)线程与进程

进程是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。进程实体由程序段, 数据段 PCB(进程控制块)组成。

线程可以看做轻量级进程,线程是进程的执行单元,是进程调度的基本单位。

(2)多线程中的上下文切换
在上下文切换过程中,CPU 会停止处理当前运行的程序,并保存当前程序运行的具体位置以便之后继续运行。在程序中,上下文切换过程中的“页码”信息是保存在进程控制块(PCB)中的。PCB 还经常被称作“切换桢”(switchframe)。“页码”信息会一直保存到 CPU 的内存中,直到他们被再次使用。
上下文切换是存储和恢复 CPU 状态的过程,它使得线程执行能够从中断点恢复执行。上下文切换是多任务操作系统和多线程环境的基本特征。

(3)多线程同步和互斥实现方法

1、线程同步

指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。

2、线程互斥

指对于共享的进程系统资源,在各单个线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。线程互斥可以看成是一种特殊的线程同步。

线程间的同步方法大体可分为两类:用户模式和内核模式。

内核模式:指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,
用户模式:就是不需要切换到内核态,只在用户态完成操作。
用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。

内核模式下的方法有:事件,信号量,互斥量。

(3)进程调度算法
1、实时系统

FIFO(First Input First Output,先进先出算法)

SJF(Shortest Job First,最短作业优先算法)

SRTF(Shortest Remaining Time First,最短剩余时间优先算法)。
2、交互式系统

RR(Round Robin,时间片轮转算法)

HPF(Highest Priority First,最高优先级算法)

多级队列

最短进程优先

保证调度,彩票调度,公平分享调度。

二、Java线程

(1)创建线程的方式
1、继承 Thread 类创建线程类
2、通过 Runnable 接口创建线程类
3、通过 Callable 和 Future 创建线程
4、通过线程池创建

(2) 守护线程和本地线程
在Java中有两类线程:用户线程 (User Thread)、守护线程 (Daemon Thread、gc线程、Finalizer线程)
守护线程和用户线程的区别在于:守护线程依赖于创建它的线程,而用户线程则不依赖。

扩展:

Thread Dump 打印出来的线程信息,含有 daemon 字样的线程即为守护
进程,可能会有:服务守护进程、编译守护进程、windows 下的监听 Ctrl+break
的守护进程、Finalizer 守护进程、引用处理守护进程、GC 守护进程。

(3)Java线程的生命周期

新建(New):创建后尚位启动的线程的状态
运行(Runnable):包含Running和Ready
无限期等待(Waiting):不会被分配CPU执行时间,需要显式呗唤醒
限期等待(Timed Waiting):在一定时间后会由系统自动唤醒
阻塞(Blocked):等待排它锁
结束(Terminated):已终止线程的状态,线程已经结束执行

(4)线程调度的方法
1、wait()

使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;

2、sleep()

使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException异常;
3、notify()

唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;

4、notityAll()

唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;

(5)线程调度算法

有两种调度模型:分时调度模型和抢占式调度模型。

分时调度模型是指让所有的线程轮流获得 cpu 的使用权,并且平均分配每个线程占
用的 CPU 的时间片。

抢占式调度模型是指优先让可运行池中优先级高的线程占用
CPU,如果可运行池中的线程优先级相同,那么就随机选择一个线程,使其占用
CPU。处于运行状态的线程会一直运行,直至它不得不放弃 CPU。

java虚拟机采用时间片轮转的方式。可以设置线程的优先级,会映射到下层的系统上面的优
先级上,如非特别需要,尽量不要用,防止线程饥饿。

三、死锁

(1)死锁产生的4个必要条件

1、互斥条件

2、请求和保持条件

3、不可抢占条件

4)循环等待条件

(2)死锁类型

1、锁顺序死锁(交错执行)

2、动态锁顺序死锁

3、协作对象之间发生死锁(隐式获取两个锁)

(3)避免死锁的方法

1、固定加锁的顺序(针对锁顺序死锁)
2、开放调用(针对对象之间协作造成的死锁)

3、使用定时锁-->tryLock()
4、如果等待获取锁时间超时,则抛出异常而不是一直等待!

(4)死锁检测

JDK提供了两种方式检测:
JconsoleJDK自带的图形化界面工具,使用JDK给我们的的工具JConsole
Jstack是JDK自带的命令行工具,主要用于线程Dump分析。
1、Jstack命令

jstack是java虚拟机自带的一种堆栈跟踪工具。jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息。 Jstack工具可以用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。

2、JConsole工具

Jconsole是JDK自带的监控工具,在JDK/bin目录下可以找到。它用于连接正在运行的本地或者远程的JVM,对运行在Java应用程序的资源消耗和性能进行监控,并画出大量的图表,提供强大的可视化界面。而且本身占用的服务器内存很小,甚至可以说几乎不消耗。

(5)死锁、活锁、饥饿

1、死锁

是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
2、活锁

任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,
失败,尝试,失败。
活锁和死锁的区别在于,处于活锁的实体是在不断的改变状态,所谓的“活”, 而
处于死锁的实体表现为等待;活锁有可能自行解开,死锁则不能。
3、饥饿

一个或者多个线程因为种种原因无法获得所需要的资源,导致一直无法执
行的状态。
Java 中导致饥饿的原因:

1)高优先级线程吞噬所有的低优先级线程的 CPU 时间。
2)线程被永久堵塞在一个等待进入同步块的状态,因为其他线程总是能在它之前
持续地对该同步块进行访问。
3)线程在等待一个本身也处于永久等待完成的对象(比如调用这个对象的 wait 方 法),因为其他线程总是被持续地获得唤醒。

四、扩展

(1)避免死锁

预防死锁的几种策略,会严重地损害系统性能。因此在避免死锁时,要施加较弱的限制,从而获得 较满意的系统性能。由于在避免死锁的策略中,允许进程动态地申请资源。因而,系统在进行资源分配之前预先计算资源分配的安全性。若此次分配不会导致系统进入不安全的状态,则将资源分配给进程;否则,进程等待。其中最具有代表性的避免死锁算法是银行家算法。

银行家算法:首先需要定义状态和安全状态的概念。系统的状态是当前给进程分配的资源情况。因此,状态包含两个向量Resource(系统中每种资源的总量)和Available(未分配给进程的每种资源的总量)及两个矩阵Claim(表示进程对资源的需求)和Allocation(表示当前分配给进程的资源)。安全状态是指至少有一个资源分配序列不会导致死锁。当进程请求一组资源时,假设同意该请求,从而改变了系统的状态,然后确定其结果是否还处于安全状态。如果是,同意这个请求;如果不是,阻塞该进程知道同意该请求后系统状态仍然是安全的。

(2)检测死锁

首先为每个进程和每个资源指定一个唯一的号码;

然后建立资源分配表和进程等待表。

(3)解除死锁

当发现有进程死锁后,便应立即把它从死锁状态中解脱出来,常采用的方法有:

夺资源:从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态;

撤消进程:可以直接撤消死锁进程或撤消代价最小的进程,直至有足够的资源可用,死锁状态.消除为止;所谓代价是指优先级、运行代价、进程的重要性和价值等。

五、问题

(1)进程与线程的区别

进程是资源分配的最小单位
线程是CPU调度的最小单位
一个程序必须有一个进程,一个进程必须有一个线程

(2)Thread中start和run方法的区别

调用start()方法会创建一个新的子线程并启动
run()方法只是Thread的一个普通方法的调用

(3)Thread和Runnable的关系

Thread是实现了Runnable接口的类,使得run支持多线程
因类的单一继承原则,推荐多使用Runnable接口

(4)wait()和sleep()的区别

sleep是Thread类的方法,wait是Object类中定义的方法
sleep()方法可以在任何地方使用
wait()方法只能在sychronized方法或synchronized块中使用
Thread.sleep只会让出CPU,不会导致锁行为的改变
Object.wait不仅让出CPU,还会释放已经占有的同步资源锁

(5)锁池与等待池

在java中,每个对象都有两个池,锁(monitor)池和等待池

wait() ,notifyAll(),notify() 三个方法都是Object类中的方法.

锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。

等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁(因为wait()方法必须出现在synchronized中,这样自然在执行wait()方法之前线程A就已经拥有了该对象的锁),同时线程A就进入到了该对象的等待池中。如果另外的一个线程调用了相同对象的notifyAll()方法,那么处于该对象的等待池中的线程就会全部进入该对象的锁池中,准备争夺锁的拥有权。如果另外的一个线程调用了相同对象的notify()方法,那么仅仅有一个处于该对象的等待池中的线程(随机)会进入该对象的锁池.

(6)notify和notifyAll的区别

notifyAll:会让所有处于等待池的线程全部进入锁池去竞争获取锁的机会
notify:会随机让一个处于等待池中的线程进入锁池去竞争获取锁的机会

(7)interrupt函数

通知线程应该中断了

  • 如果线程处于阻塞状态,那么线程将立即退出被阻塞状态,抛出一个InterruptedException异常
  • 如果线程处于正常活动状态,那么会将该线程的中断标志设置为true。被设置中断标志的线程将继续正常运行,不受影响

(8)线程状态以及状态之间的转换

Java 并发总结——进程与线程相关推荐

  1. Java中的进程与线程

    2019独角兽企业重金招聘Python工程师标准>>> Java中的进程与线程 概念 进程与线程,本质意义上说, 是操作系统的调度单位,可以看成是一种操作系统 "资源&qu ...

  2. 学习笔记(33):Python网络编程并发编程-进程池线程池

    立即学习:https://edu.csdn.net/course/play/24458/296451?utm_source=blogtoedu 进程池与线程池: 一般应用在网站上,进程池或线程池最大的 ...

  3. java并发编程实践(2)线程安全性

    [0]README 0.0)本文部分文字描述转自:"java并发编程实战", 旨在学习"java并发编程实践(2)线程安全性" 的相关知识: 0.1)几个术语( ...

  4. Java并发(五)线程池使用番外-分析RejectedExecutionException异常

    Java并发(五)线程池使用番外-分析RejectedExecutionException异常 参考文章: (1)Java并发(五)线程池使用番外-分析RejectedExecutionExcepti ...

  5. 并发和多线程(一)并发、进程、线程概念

    一.并发.进程.线程的基本概念和综述 1.1 并发 两个或者更多的任务(独立的活动)同时发生(进行):一个程序同时执行多个独立的任务: 以往计算机,单核cpu(中央处理器):某一个时刻只能执行一个任务 ...

  6. Python 第八篇:异常处理、Socket语法、SocketServer实现多并发、进程和线程、线程锁、GIL、Event、信号量、进程间通讯...

    本节内容: 异常处理.Socket语法.SocketServer实现多并发.进程和线程.线程锁.GIL.Event.信号量.进程间通讯.生产者消费者模型.队列Queue.multiprocess实例 ...

  7. 【Java进阶】Java并发类库提供的线程池有哪几种? 分别有什么特点?

    我在专栏第 17 讲中介绍过线程是不能够重复启动的,创建或销毁线程存在一定的开销,所以利用线程池技术来提高系统资源利用效率,并简化线程管理,已经是非常成熟的选择. 今天我要问你的问题是,Java 并发 ...

  8. Java 并发 多线程:创建线程的四种方式

    Java 并发 多线程: 创建线程的四种方式 继承 Thread 类并重写 run 方法 实现 Runnable 接口 实现 Callable 接口 使用线程池的方式创建 1. 通过继承 Thread ...

  9. Java并发编程—什么是线程?

    原文作者:way_more 原文地址:Java 多线程常见基础面试题总结,面试必看! 目录 一.什么是线程和进程? 二.简要描述线程与进程的关系 三.FAQ 一.什么是线程和进程? 1.1. 何为进程 ...

最新文章

  1. 春节在家不再无聊,这份2019 AI研究进展回顾陪伴你
  2. 现代操作系统: 第八章 多处理机系统
  3. TensorFlow中RNN实现的正确打开方式
  4. JavaSE(八)——StringBuffer类、Arrays类、数组排序
  5. 材料成型计算机模拟第三版,材料成型计算机模拟实验报告模板学习.doc
  6. 数据可视化 信息可视化_可视化哲学的黎明
  7. WPF 实现3D翻转倒计时控件~
  8. Laravel5.5之事件监听、任务调度、队列
  9. suse linux系统备份,suse linux enterprise server 11 sp3 版克隆安装ebs r12.1.3注意事项
  10. qt中dll缺失以及无法启动程序的正确解决方法
  11. pythonlauncher可以卸载吗_python的launcher用法知识点总结
  12. 计算机网络超详细笔记(三):数据链路层
  13. access和filemaker_四个替代微软Access的开源产品
  14. 推荐10个堪称神器的学习网站
  15. python算p值_Python sklearn-如何计算p值
  16. 输入单号查快递:如何用快递单号查询快递信息
  17. 简单c语言实现的成语接龙小游戏
  18. 动手学习深度学习-深度学习基础
  19. Unity3D研究院之挥动武器产生的剑痕特效(四十七)
  20. IDEA插件【美化插件】

热门文章

  1. java的scanner的方法_Java Scanner reset()方法
  2. docker 容器启动顺序_Docker容器启动时初始化Mysql数据库
  3. 买卖股票类问题动态规划解法(Leetcode题解-Python语言)
  4. [JavaWeb-Bootstrap]CSS样式和JS插件
  5. [C++11]forward完美转发
  6. Java语法基础50题训练(上)
  7. [剑指offer]面试题41:和为s的两个数字VS和为s的连续正数序列
  8. Pycharm安装第三方库
  9. 找出第二小元素(算法导论第三版9.1-1题)
  10. Fibonacci again and again HDU - 1848(尼姆博弈+SG函数的运用+SG函数详解)