JUC并发编程学习(二)-进程和线程知识回顾

简介: JUC并发编程学习(二)-进程和线程知识回顾

进程线程知识回顾

进程:就是一个应用程序,如QQ.exe ,music.exe程序

线程:一个进程中可能包含多个线程,至少包含一个。


在java中一个应用程序至少有几个线程?

2个, main线程、GC线程


并行、并发是什么?


并发:指两个或多个时间在同一时间段发生。并发就是是串行的同步,一个任务执行完成才执行下一任务;

多线程、多个线程操作一个资源类,快速交替的过程。


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

20200401134307494.png

你吃饭,吃到一半,电话来了,3种情况:

1.先吃完饭,再接电话(单线程)

2.先接电话再吃 (交替、并发)

3.边吃边接电话 (并行)

并发编程的主要目的,充分利用CPU的资源,提高性能

什么是线程?

线程:线程是进程中的一个执行单位,负责当前进程中程序的执行,一个进程至少有一个线程。

线程的6个状态:

public enum State {
NEW,
RUNNABLE,
BLOCKED,    //阻塞
WAITING, // 等待
TIMED_WAITING, // 延时等待
TERMINATED; //终止,结束
}

线程状态。 线程可以处于以下状态:

    NEW
    尚未启动的线程,处于此状态。
    RUNNABLE
    在Java虚拟机中执行的线程,处于此状态。
    BLOCKED
    被阻塞等待监视器锁定的线程,处于此状态。
    WAITING
    正在等待 执行特定动作的线程,处于此状态。
    TIMED_WAITING
    正在等待另一个线程执行动作达到指定等待时间的线程,处于此状态。
    TERMINATED(终止、结束)
    已退出的线程,处于此状态。

wait / sleep 的区别: 从4个方面说明

1.类:

wait属于Object类

sleep 属于Thread类,谁调用的谁睡觉!

A 调用了B的sleep方法? A睡觉

2.是否释放锁

sleep抱着锁睡觉

wait会释放锁.


它们都可以暂停执行线程,但是sleep方法没有释放锁,而wait方法释放了锁。


调用sleep(xxx)会让当前线程暂停(又称此为“睡眠或休眠”)执行指定的时间xxx毫秒,xxx越大等待时间越长,比如:sleep(1000)将暂停1000毫秒执行,此时将执行机会让给其他线程,即把使用CPU的机会给其他线程,但该对象的锁依然保持,所以休眠时间结束后会自动恢复,即该线程回到就绪状态。


调用wait()方法,会使当前线程放弃对象的锁,即线程暂停执行,进入对象的等待池。此时,只有调用该对象的notify()方法或notifyAll()方法,才能唤醒等待池中的线程进入等锁池,但线程只有再次获得对象的锁,才能进入就绪状态。


3.使用范围不同


wait、notify、notifyAll只能使用在同步方法或者同步代码中;

sleep可以使用到任意地方


4.异常

sleep必须捕获异常

wait不需要捕获异常


wait(),notify()和suspend(),resume()之间的区别


1、sleep()、 suspend() 和 resume() 、yield() 阻塞时都不会释放占用的锁(如果占用了的话),wait(),notify()方法阻塞时要释放占用的锁。这是最核心的区别,这一核心区别导致了一系列细节上的区别(如下几条区别)。


2、wait(),notify()方法属于Object。 前面叙述的所有方法都隶属于 Thread 类,但是这一对却直接隶属于 Object 类。也就是说,所有对象都拥有这一对方法。初看起来这十分不可思议,但是实际上却是很自然的,因为这一对方法阻塞时要释放占用的锁,而锁是任何对象都具有的,调用任意对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放。而调用任意对象的notify()方法则导致因调用该对象的 wait() 方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。


3、wait(),notify()方法必须在synchronized方法或块中调用。前面叙述的所有方法都可在任何位置调用,但是这一对方法却必须在 synchronized 方法或块中调用,理由也很简单,只有在synchronized 方法或块中,当前线程才占有锁,才有锁可以释放。同样的道理,调用这一对方法的对象上的锁必须为当前线程所拥有,这样才有锁可以释放。因此,这一对方法调用必须放置在这样的 synchronized 方法或块中,该方法或块的上锁对象就是调用这一对方法的对象。若不满足这一条件,则程序虽然仍能编译,但在运行时会出现IllegalMonitorStateException 异常。


为什么wait()方法和notify()/notifyAll()方法要在同步块中被调用


这是JDK强制的,wait()方法和notify()/notifyAll()方法在调用前都必须先获得对象的锁。


wait() 和 notify()与操作系统进程间的通信机制结合


wait() 和 notify() 方法的上述特性决定了它们经常和synchronized 方法或块一起使用。

将它们和操作系统的进程间通信机制作一个比较就会发现它们的相似性:


synchronized方法或块提供了类似于操作系统原语的功能,它们的执行不会受到多线程机制的干扰,而这一对方法则相当于 block 和wakeup 原语(这一对方法均声明为 synchronized)。它们的结合使得我们可以实现操作系统上一系列精妙的进程间通信的算法(如信号量算法),并用于解决各种复杂的线程间通信问题。


关于 wait() 和 notify() 方法最后再说明两点:


第一:调用 notify() 方法导致解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随机选取的,我们无法预料哪一个线程将会被选择,所以编程时要特别小心,避免因这种不确定性而产生问题——虚假唤醒。


第二:除了 notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用 notifyAll() 方法将把因调用该对象的 wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。


谈到阻塞,就不能不谈一谈死锁,略一分析就能发现,suspend() 方法和不指定超时期限的 wait() 方法的调用都可能产生死锁。遗憾的是,Java 并不在语言级别上支持死锁的避免,我们在编程中必须小心地避免死锁。


有兴趣的老爷,可以关注我的公众号【一起收破烂】,回复【006】获取2021最新java面试资料以及简历模型120套哦~




相关文章
|
19天前
|
调度 开发者 Python
深入浅出操作系统:进程与线程的奥秘
在数字世界的底层,操作系统扮演着不可或缺的角色。它如同一位高效的管家,协调和控制着计算机硬件与软件资源。本文将拨开迷雾,深入探索操作系统中两个核心概念——进程与线程。我们将从它们的诞生谈起,逐步剖析它们的本质、区别以及如何影响我们日常使用的应用程序性能。通过简单的比喻,我们将理解这些看似抽象的概念,并学会如何在编程实践中高效利用进程与线程。准备好跟随我一起,揭开操作系统的神秘面纱,让我们的代码运行得更加流畅吧!
|
19天前
|
消息中间件 Unix Linux
【C语言】进程和线程详解
在现代操作系统中,进程和线程是实现并发执行的两种主要方式。理解它们的区别和各自的应用场景对于编写高效的并发程序至关重要。
46 6
|
19天前
|
调度 开发者
深入理解:进程与线程的本质差异
在操作系统和计算机编程领域,进程和线程是两个核心概念。它们在程序执行和资源管理中扮演着至关重要的角色。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
42 5
|
17天前
|
算法 调度 开发者
深入理解操作系统:进程与线程的管理
在数字世界的复杂编织中,操作系统如同一位精明的指挥家,协调着每一个音符的奏响。本篇文章将带领读者穿越操作系统的幕后,探索进程与线程管理的奥秘。从进程的诞生到线程的舞蹈,我们将一起见证这场微观世界的华丽变奏。通过深入浅出的解释和生动的比喻,本文旨在揭示操作系统如何高效地处理多任务,确保系统的稳定性和效率。让我们一起跟随代码的步伐,走进操作系统的内心世界。
|
19天前
|
调度 开发者
核心概念解析:进程与线程的对比分析
在操作系统和计算机编程领域,进程和线程是两个基本而核心的概念。它们是程序执行和资源管理的基础,但它们之间存在显著的差异。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
38 4
|
1月前
|
并行计算 数据处理 调度
Python中的并发编程:探索多线程与多进程的奥秘####
本文深入探讨了Python中并发编程的两种主要方式——多线程与多进程,通过对比分析它们的工作原理、适用场景及性能差异,揭示了在不同应用需求下如何合理选择并发模型。文章首先简述了并发编程的基本概念,随后详细阐述了Python中多线程与多进程的实现机制,包括GIL(全局解释器锁)对多线程的影响以及多进程的独立内存空间特性。最后,通过实例演示了如何在Python项目中有效利用多线程和多进程提升程序性能。 ####
|
1月前
|
Java
java小知识—进程和线程
进程 进程是程序的一次执行过程,是系统运行的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如CPU时间,内存空间,文件,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。 线程 线程,与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间做切换工作时,负担要比
29 1
|
29天前
|
监控 JavaScript 前端开发
python中的线程和进程(一文带你了解)
欢迎来到瑞雨溪的博客,这里是一位热爱JavaScript和Vue的大一学生分享技术心得的地方。如果你从我的文章中有所收获,欢迎关注我,我将持续更新更多优质内容,你的支持是我前进的动力!🎉🎉🎉
23 0
|
2月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
58 1
C++ 多线程之初识多线程
|
2月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
27 3