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套哦~




相关文章
|
2月前
|
Java 程序员 调度
【JAVA 并发秘籍】进程、线程、协程:揭秘并发编程的终极武器!
【8月更文挑战第25天】本文以问答形式深入探讨了并发编程中的核心概念——进程、线程与协程,并详细介绍了它们在Java中的应用。文章不仅解释了每个概念的基本原理及其差异,还提供了实用的示例代码,帮助读者理解如何在Java环境中实现这些并发机制。无论你是希望提高编程技能的专业开发者,还是准备技术面试的求职者,都能从本文获得有价值的见解。
45 1
|
25天前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
1月前
|
监控 Java 调度
【Java学习】多线程&JUC万字超详解
本文详细介绍了多线程的概念和三种实现方式,还有一些常见的成员方法,CPU的调动方式,多线程的生命周期,还有线程安全问题,锁和死锁的概念,以及等待唤醒机制,阻塞队列,多线程的六种状态,线程池等
105 6
【Java学习】多线程&JUC万字超详解
|
17天前
|
并行计算 API 调度
探索Python中的并发编程:线程与进程的对比分析
【9月更文挑战第21天】本文深入探讨了Python中并发编程的核心概念,通过直观的代码示例和清晰的逻辑推理,引导读者理解线程与进程在解决并发问题时的不同应用场景。我们将从基础理论出发,逐步过渡到实际案例分析,旨在揭示Python并发模型的内在机制,并比较它们在执行效率、资源占用和适用场景方面的差异。文章不仅适合初学者构建并发编程的基础认识,同时也为有经验的开发者提供深度思考的视角。
|
2月前
|
设计模式 Java 调度
JUC线程池: ScheduledThreadPoolExecutor详解
`ScheduledThreadPoolExecutor`是Java标准库提供的一个强大的定时任务调度工具,它让并发编程中的任务调度变得简单而可靠。这个类的设计兼顾了灵活性与功能性,使其成为实现复杂定时任务逻辑的理想选择。不过,使用时仍需留意任务的执行时间以及系统的实际响应能力,以避免潜在的调度问题影响应用程序的行为。
63 1
|
2月前
|
数据采集 并行计算 安全
Python并发编程:多进程(multiprocessing模块)
在处理CPU密集型任务时,Python的全局解释器锁(GIL)可能会成为瓶颈。为了充分利用多核CPU的性能,可以使用Python的multiprocessing模块来实现多进程编程。与多线程不同,多进程可以绕过GIL,使得每个进程在自己的独立内存空间中运行,从而实现真正的并行计算。
|
2月前
|
Java API 调度
JUC线程池: FutureTask详解
总而言之,FutureTask是Java并发编程中一个非常实用的类,它在异步任务执行及结果处理方面提供了优雅的解决方案。在实现细节方面可以搭配线程池的使用,以及与Callable接口的配合使用,来完成高效的并发任务执行和结果处理。
30 0
|
2月前
|
消息中间件 存储 安全
python多进程并发编程之互斥锁与进程间的通信
python多进程并发编程之互斥锁与进程间的通信
|
2月前
|
Java 程序员 容器
【多线程面试题二十四】、 说说你对JUC的了解
这篇文章介绍了Java并发包java.util.concurrent(简称JUC),它是JSR 166规范的实现,提供了并发编程所需的基础组件,包括原子更新类、锁与条件变量、线程池、阻塞队列、并发容器和同步器等多种工具。
|
3月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能