第11章-多线程与并发
c++的并发操作(多线程)
c++的并发操作(多线程)
C++11标准在标准库中为多线程提供了组件,这意味着使⽤C++编写与平台⽆关的多线程程序成为可能,⽽C++程序的可移植性也得到了有⼒的保证。另外,并发编程可提⾼应⽤的性能,这对对性能锱铢必较的C++程序员来说是值得关注的。
1. 何为并发
并发指的是两个或多个独⽴的活动在同⼀时段内发⽣。⽣活中并发的例⼦并不少,例如在跑步的时候你可能同时在听⾳乐;在看电脑显⽰器的同时你的⼿指在敲击键盘。这时我们称我们⼤脑并发地处理这些事件,只不过我们⼤脑的处理是有次重点的:有时候你会更关注你呼吸的频率,⽽有时候你更多地被美妙的⾳乐旋律所吸引。这时我们可以说⼤脑是⼀种并发设计的结构。这种次重点在计算机程序设计中,体现为某⼀个时刻只能处理⼀个操作。
与并发相近的另⼀个概念是并⾏。它们两者存在很⼤的差别。并⾏就是同时执⾏,计算机在同⼀时刻,在某个时间点上处理两个或以上的操作。判断⼀个程序是否并⾏执⾏,只需要看某个时刻上是否多两个或以上的⼯作单位在运⾏。⼀个程序如果是单线程的,那么它⽆法并⾏地运⾏。利⽤多线程与多进程可以使得计算机并⾏地处理程序(当然,前提是该计算机有多个处理核⼼)。
并发:同⼀时间段内可以交替处理多个操作:
图中整个安检系统是⼀个并发设计的结构。两个安检队列队⾸的⼈竞争这⼀个安检窗⼝,两个队列可能约定交替着进⾏安检,也可能是⼤家同时竞争安检窗⼝(通信)。后⼀种⽅式可能引起冲突:因为⽆法同时进⾏两个安检操作。在逻辑上看来,这个安检窗⼝是同时处理这两个队列。
并⾏:同⼀时刻内同时处理多个操作:
第11章 多线程
取款。
Java使用关键字synchonized修饰对象的同步代码 块或同步方法。 “同步”语句块或方法:“原子”操作,让该操作 是不可分割的。
synchonized 方法签名{ …… } synchonized (对象) { …… }
◦ 同步代码块的处理与之类似,只是同步代码块可以在 synchonized后指定加锁的对象,除了this对象外,还可 以为其他对象加锁。
线程(thread):进程的执行单元,线程在进程中 是独立的、并发的执行流。
◦ 当进程被初始化后,主线程就被创建了,该线程从程序入 口main()方法开始运行。
多线程:进程内创建的多个线程,每个线程互相独立。使
得同一个进程可以同时并发处理多个任务。
进程和线程的关系
◦ 每个线程拥有自己独立的数据区:程序计数器、栈内存等, 创建新线程时这些数据区会一并创建。
【例11-1】通过Thread类创建线程。
Runnable接口只有一个run()方法。
◦ 因为Runnable接口和Thread类之间没有继承关系,所以 不能直接赋值。 ◦ 为了使run()方法中的代码在单独的线程中运行,仍需要一 个Thread实例,实现对Runnable对象的包装。这样,线 程相当于由两部分代码组成:Thread提供线程的支持, Runnable实现类提供线程执行体,即线程任务部分的代 码。 ◦ Thread(Runnable thread)构造方法用于包装Runnable 实现类对象,并创建线程。
如何在Java中使用多线程进行并发编程
如何在Java中使用多线程进行并发编程
Java作为一种面向对象的编程语言,可以支持多线程并发编程。使用Java多线程可以使程序能够有效地利用多核处理器,提高程
序的计算速度和并发性能。在本文中,我们将探讨如何在Java中
使用多线程进行并发编程。
一、什么是多线程
多线程是指在单个程序中同时运行多个线程,每个线程都可以
独立地执行不同的任务。与单线程相比,多线程可以提高程序的
并发性能,使程序更加高效地执行各种任务。
Java中使用多线程编程,可以使用线程对象实现并发性能。线
程对象是Java平台提供的一种机制,可以使多个线程在同一个应
用程序中运行。线程对象可以直接通过Java API访问,从而为开
发人员提供了创建和控制线程的方法。
二、创建线程
Java中实现多线程最常用的方法是创建Thread类的对象,并重
写run()方法。线程执行的代码通常写在run()方法中。创建线程的
方式有两种:一种是继承Thread类,另一种是实现Runnable接口。
继承Thread类创建线程
继承Thread类,必须实现run()方法。run()方法是线程的一个
主要方法,是用来描述线程如何运行的。
```
public class MyThread extends Thread {
public void run() {
// 线程执行的代码
}
}
```
实现Runnable接口创建线程
实现Runnable接口,必须实现run()方法。Thread类实现了Runnable接口,构造函数中可以传递一个Runnable类型的参数,这样可以使一个Thread对象关联一个Runnable对象,从而启动一个新的线程。
Shell脚本中的高级技巧使用多线程和并发处理
Shell脚本中的高级技巧使用多线程和并发处
理
Shell脚本中的高级技巧:使用多线程和并发处理
Shell脚本是一种在Unix或类Unix操作系统上运行的脚本语言,它
通过执行一系列命令来完成特定任务。在Shell脚本中,我们通常使用
串行方法执行命令,即按照顺序逐个执行命令。然而,在某些情况下,使用多线程和并发处理可以提高脚本的执行效率。本文将介绍Shell脚
本中的高级技巧,即如何使用多线程和并发处理来优化脚本的执行。
1. 多线程操作
多线程是指在一个程序中同时执行多个线程,每个线程可以独立运行,执行不同的任务。在Shell脚本中,我们可以使用以下方法实现多
线程操作:
方法一:使用&符号后台执行任务
通过在命令后添加&符号,可以将任务放入后台执行,实现多线程
效果。例如:
```shell
#!/bin/bash
task1 &
task2 &
task3 &
task4 &
wait
echo "所有任务执行完成"
```
上述脚本中,task1、task2、task3、task4分别代表四个需要执行的任务。通过在每个任务后添加&符号,实现了这四个任务的并发执行。wait命令用于等待所有任务执行完成后再继续输出完成信息。
方法二:使用xargs命令执行并发任务
xargs命令是Linux系统中一个常用的命令行工具,用于将标准输入数据转换成命令行参数。通过结合xargs命令和并发参数-P,可以实现并发执行任务。例如:
```shell
#!/bin/bash
tasks=('task1' 'task2' 'task3' 'task4')
软件工程中的并发设计与多线程应用实践
软件工程中的并发设计与多线程应用实践
在当今数字化时代,软件的应用已经渗透到我们生活的方方面面。为了提供更
好的用户体验和效率,软件工程师们不断追求并发设计与多线程应用的技术突破。本文将探讨软件工程中的并发设计原则以及多线程应用的实践经验。
一、并发设计原则
并发设计是指在软件开发中,同时处理多个任务或多个线程的设计方法。在进
行并发设计时,有一些原则需要遵循。
首先,要避免资源竞争。资源竞争是指多个线程同时访问共享资源,导致数据
不一致或程序崩溃的情况。为了避免资源竞争,我们可以使用锁机制或者并发控制算法来保证资源的互斥访问。
其次,要保证线程安全。线程安全是指多个线程同时访问一个对象时,不会出
现任何问题。为了保证线程安全,我们可以使用同步机制,如互斥锁、条件变量等。
另外,要进行合理的任务划分。将任务划分为多个子任务,每个子任务由一个
线程处理,可以提高并发处理的效率。任务划分的原则是将相互独立的任务划分为不同的线程,尽量避免线程之间的依赖关系。
最后,要进行适当的线程通信。线程通信是指多个线程之间传递消息或者共享
数据的过程。为了实现线程通信,我们可以使用信号量、消息队列等机制。
二、多线程应用实践经验
在软件工程中,多线程应用是一项重要的技术。下面将分享一些多线程应用的
实践经验。
首先,要合理规划线程数量。过多的线程会导致系统资源的浪费,过少的线程则可能影响程序的并发性能。因此,我们需要根据实际情况来规划线程的数量,确保线程的数量能够充分利用系统资源,同时又不会过多拖慢程序的执行速度。
其次,要注意线程间的依赖关系。在多线程应用中,线程之间可能存在依赖关系,一个线程的执行结果可能会影响到其他线程的执行。为了避免出现问题,我们需要对线程之间的依赖关系进行合理的设计和管理。
C++11并发指南一(C++11多线程初探)
C++11并发指南⼀(C++11多线程初探)
引⾔
C++11 ⾃2011年发布以来已经快两年了,之前⼀直没怎么关注,直到最近⼏个⽉才看了⼀些 C++11 的新特性,今后⼏篇博客我都会写⼀些关于 C++11 的特性,算是记录⼀下⾃⼰学到的东西吧,和⼤家共勉。
相信 Linux 程序员都⽤过 Pthread, 但有了 C++11 的 std::thread 以后,你可以在语⾔层⾯编写多线程程序了,直接的好处就是多线程程序的可移植性得到了很⼤的提⾼,所以作为⼀名 C++ 程序员,熟悉 C++11 的多线程编程⽅式还是很有益处的。
如果你对 C++11 不太熟悉,建议先看看维基百科上关于 C++11 新特性的介绍,,,另外C++之⽗的关于也是必看的,我也收集了⼀些关于C++11的资料,供⼤家查阅:
资料汇
C++0x/C++11 Support in GCC:
What is C++0x:
Overview of the New C++:
Overview of the New C++ (C++0x).pdf:
A Brief Look at C++0x:
Summary of C++11 Feature Availability in gcc and MSVC:
C++ 11: Come Closer:
C++11 threads, locks and condition variables:
Move Semantics and Perfect Forwarding in C++11:
C++11 Concurrency:
软件测试中的并发和多线程测试技巧
软件测试中的并发和多线程测试技巧在软件测试中,并发和多线程测试是非常重要的技巧之一。随着计
算机技术的不断发展和软件的复杂性增加,同时也带来了并发和多线
程的挑战。在本文中,我将介绍并发和多线程测试的基础知识,并分
享一些有效的测试技巧。
一、并发和多线程测试简介
在软件开发中,如果一个应用程序要处理多个任务或事件,就需要
使用并发和多线程技术。并发是指同时执行多个任务的能力,而多线
程是实现并发的一种方法。并发和多线程技术可以提高软件的性能和
响应速度,但也带来了一些潜在的问题和挑战。
二、并发和多线程测试的挑战
并发和多线程测试的挑战主要体现在以下几个方面:
1. 竞争条件:当多个线程同时访问共享资源时,可能会发生竞争条件。竞争条件可能会导致数据一致性问题和不确定的结果。
2. 死锁:死锁是指多个线程相互等待对方释放资源而无法继续执行
的情况。死锁可能会导致系统崩溃或无响应。
3. 饥饿:饥饿是指某个线程长时间无法获得所需资源的情况。饥饿
可能会导致系统性能下降或响应延迟。
4. 内存泄漏:并发和多线程测试可能会导致内存泄漏问题。内存泄
漏可能会使系统的内存消耗过大,最终导致系统崩溃或出现性能问题。
三、并发和多线程测试技巧
为了有效地进行并发和多线程测试,可以采用以下几种技巧:
1. 并发和多线程测试计划:在进行并发和多线程测试之前,制定详细的测试计划是非常重要的。测试计划应包括测试的范围、测试的目标、测试环境的搭建和测试用例的设计等。
2. 并发和多线程测试工具:使用合适的测试工具可以简化测试的过程,并提高测试的效率和准确性。常用的并发和多线程测试工具包括Junit、TestNG和JMeter等。
第11章 多线程-2
2009
CS&T Information Course
线程的优先级
• 线程可以设定优先级,高优先级的线程可以安排 在低优先级线程之前完成。 • Java中,线程的优先级从低到高以整数1~10 表示,共分为10级。设置优先级是通过调用线 程对象的setPriority()方法来进行的。 setPriority() • 默认优先级为5,优先级高的线程获得CPU时间 的机会相对较高。 • 示例:ThreadPriority.java
2009
CS&T Information Course
线程之间的通信
• 示例:PipeTest.java • 上面的例子拥有一个产生随机数的 生产者线程;一个在屏幕上输出结 果的消费者线程。这个程序不会自 动结束,用户可以通过Ctrl+C键 来终止它。
2009
CS&T Information Course
2009
CS&T Information Course
线程控制(线程调度)
• 如果对一个同步对象x发出一个notify()调用, 则从阻塞状态的线程中唤醒一个线程去等待该 对象的锁标记,一旦获得锁标记,便从上一次 wait()处接着运行。 • notifyAll() notifyAll()方法唤醒所有因一个同步对象调用 wait()阻塞的所有线程。 • 示例:ProducerConsumer3.java • 注意:wait()/notify()必须在同步块中由同步 对象调用。
第11章 多线程-1
CS&T Information Course
第11章 多线程
2009
CS&T Information Course
本章学习目标
• • • • 理解多线程的概念 掌握如何创建线程 掌握如何使线程同步 理解线程优先级、 理解线程优先级、状态和线程调度
2009
CS&T Information Course
2009
CS&T Information Course
练习2 练习
• 通过继承Thread 类来编写一个线程类,类名为 通过继承Thread 类来编写一个线程类, 该线程能够在命令行显示线程的名称, SubThread 。该线程能够在命令行显示线程的名称, 然后随机休眠小于1秒的时间, 然后随机休眠小于1秒的时间,最后显示线程结束信 “finished”+线程名 线程名。 息: “finished”+线程名。 • 编写Application,在其中创建SubThread类的三 编写Application 在其中创建SubThread Application, SubThread类的三 个对象t1 t2、t3,它们的名称分别为"First" t1、 "First"、 个对象t1、t2、t3,它们的名称分别为"First"、" Second"、 Third",并启动这三个线程。 Second"、" Third",并启动这三个线程。 • TestClass2.java
多线程与并行
多线程与并⾏
1.进程和线程的区别?为什么要⽤多线程?多线程适合在哪些场合?
进程是正在运⾏的程序,线程是某个进程中的⼀个或多个执⾏执⾏流。多线程可让多个任务同时执⾏。当执⾏需要长时间才能完成的连续操作时,或者等待⽹络或其他I/O设备相应时,都可以使⽤多线程技术。
2.⼀个线程要么是前台线程妖魔是后台线程?
两者的区别是:后台线程不影响进程终⽌,⽽前台线程则会影响进程终⽌。
3.什么是同步?为什么需要同步?C#提供了什么语句可以简单的实现同步?
执⾏某语句时,在该语句执⾏之前不会执⾏其后的代码,这种⽅式称之为同步。当并⾏执⾏的多个线程同时访问某些资源时,必须考虑如何让多个线程保持同步。同步的⽬的是为了防⽌多个线程同时访问某些资源出现死锁和征⽤情况。C#提供的Lock语句可以简单的实现代码同步。
4.什么是线程池?使⽤线程池有什么好处?
线程池是在后台执⾏任务的线程集合,好处有:(1)如当某个线程⽆法进⼊线程池执⾏时将其放⼊线程队列,⾃动决定⽤哪个处理器执⾏线程池中的某个线程,⾃动调节这些线程执⾏时负载均衡问题等。另外,线程池总是在后台异步处理请求的任务,⽽不会占⽤主线程,也不会延迟主线程中后续请求的处理。
5.应⽤程序域和进程有什么区别和联系?
⼀个进程既可以只包含⼀个应⽤程序域,也可以同时包含多个相互隔离的应⽤程序域。多进程是在操作系统级别使⽤的功能,资源消耗较⼤,细节控制复杂;应⽤程序域是在应⽤程序级别使⽤的功能,⽐直接⽤多进程来实现进程管理速度快、资源消耗少⽽且安全,是轻量级的进程管理。
6.仅包含async和await 关键字的异步⽅法与⽤Task.Run调⽤的异步⽅法有何不同?
MySQL中的多线程配置与并发处理
MySQL中的多线程配置与并发处理
在当今数据密集型应用的开发中,数据库是不可或缺的一部分。MySQL作为最流行的开源关系型数据库管理系统,具有广泛的应用。数据库的性能和扩展性对于应用的稳定运行和用户体验至关重要。其中,多线程配置与并发处理是提升MySQL性能的重要因素之一。本文将探讨MySQL中的多线程配置和并发处理技术,帮助读者了解如何优化数据库性能。
一、MySQL的多线程配置
1. 线程模型
MySQL的线程模型有多种选择,其中比较常用的有单线程模型、多线程模型和线程池模型。
- 单线程模型:所有请求都在同一个线程中处理,适用于轻负载和低并发的场景,但不适合高并发和大数据量的应用。
- 多线程模型:MySQL使用多线程模型来处理并发请求,通过使用多个线程来处理不同的请求,提高了并发能力。其中,常见的多线程模型有固定线程池模型和可伸缩线程池模型。
- 线程池模型:线程池模型是一种更为高效的多线程模型,它可以动态地管理线程的创建和销毁,减少线程创建和销毁的开销,提高线程的利用率。
2. 线程配置参数
进行多线程配置前,我们需要了解一些常用的线程配置参数:
- thread_cache_size:线程缓存的大小,它决定了MySQL是否缓存空闲线程,避免频繁地创建和销毁线程。适当调整该参数可以提高并发能力。
- thread_pool_size:线程池的大小,它表示线程池中的最大线程数。适当调整该参数可以控制并发请求的数量。
- thread_handling:线程处理模式,它决定了MySQL如何处理线程的连接和资源。通常使用的模式有one-thread-per-connection、pool-of-threads和one-thread-per-connection-with-dedicated-admin-connections。
并发和多线程关系
并发和多线程是两个相关但不完全相同的概念。
并发是指多个任务在同一时间段内执行,这些任务可以是独立的、相互无关的,或者是相 互依赖的。并发可以通过多种方式实现,如多线程、多进程、协程等。
多线程是指在一个程序中同时执行多个线程,每个线程都是独立的执行流。多线程可以实 现并发,即多个线程可以在同一时间段内并发执行不同的任务。
并发和多线程关系
因此,多线程是一种实现并发的方式。通过多线程,可以将一个程序分为多个线程,每个 线程负责执行不同的任务,从而实现任务的并发执行。多线程可以提高程序的效率和响应速 度,同时也可以充分利用多核处理器的计算能力。
然而,多线程也带来了一些问题,如线程间的同步和互斥、资源竞争、死锁等。正确地管 理和控制多线程的执行是很重要的,以避免出现问题。
总结起来,多线程是一种实现并发的方式,通过将一个程序分为多个线程来并发执行不同 的任务。并发可以通过多种方式实现,多线程只是其中的一种方式。
Leabharlann Baidu
第11章 多线程(第4版)
见例11.2
11.2.2 用Runnable接口来创建线程
Runnable接口只有一个方法run(),用户可以声明一个
类并实现Runnable接口,并定义run()方法,将线程代 码写入其中,就完成了这一部分的任务。 两种创建线程对象的方式的特点:
直接继承Thread类的特点是:编写简单,可以直接操纵线 程;但缺点是若继承Thread类,就不能再继承其他类。
11.1.3 线程的调度与优先级
对应一个新建的线程,系统会遵循如下的原则为
其指定优先级: (1)新建线程将继承创建它的父线程的优先级。 父线程是指执行创建新线程对象语句所在的线程, 它可能是程序的主线程,也可能是某一个用户自 定义的线程。 (2)一般情况下,主线程具有普通优先级。
11.2 Java的Thread线程类与 Runnable接口
迚程(Process):迚程是程序的一次执行过程,是系统运 行程序的基本单位,因此迚程是动态的。 多任务(Multi task):多任务是指在一个系统中可以同时 运行多个程序,即有多个独立运行的任务,每一个任务 对应一个迚程。 线程(Thread):线程是一个比迚程更小的执行单位。一
程序(Program):程序是含有指令和数据的文件,被存 储在磁盘或其他的数据存储设备中,程序是静态的代码。
本章主要内容
程序、进程、多任务、线程的概念与区别
第11章_多线程
2 创建线程-方法2 实现Runnable接口 一个Runnable接口提供了一个 public void run()方法。
2 创建线程-练习
1. 用上述两种方法创建线程SubThread ,该线 程能够在命令行显示 “I am ”+线程名。
2. 编写Application,在其中创建SubThread 类的三个对象t1、t2、t3,它们的名称分别 为"First"、" Second"、" Third",并启动 这三个线程。
LOGO
Java面向对象程序设计
第11章 多线程
计算机学院
核心要点
献策的定义
1 2
创建自己的线程
线程的控制与状态 线程的优先级 线程的同步问题
3
4 5
1 线程的定义
不支持多任务的系统 程序2 程序3 时间
程序1
程序1 程序2 程序3
支持多任务的系统
时间
1 线程Thread
构造方法 说明 无参数 target 为运行对象 target 为运行对象,name为名称。 name为线程名称。 target 为运行对象,并作为 group线 程组的一员。 target 为运行对象,name为名称,并 作为 group线程组的一员。 具有指定的堆栈大小,其余参数同上,。 name为名称,并作为 group线程组的一 员。
11第十一讲 多线程
第十一讲: 多线程
public void run() { char c; for (int i = 0; i < 200; i++) { c = theStack.pop(); System.out.println("Consumer" + num + ": " + c); try { Thread.sleep((int)(Math.random() * 300)); } catch (InterruptedException e) { } } } }
第十一讲: 多线程
线程交互:wait和notify 方案: 自己和出租汽车司机 问题: 解答:
第十一讲: 多线程
线程交互:wait和notify wait和notify 池: 1.等待池 2.锁池
第十一讲: 多线程
线程状态:
开始 解除阻塞 阻塞事件 start() runnable 调度程序 running 同步的 获得锁 对象锁池中的阻塞 对象等待池中的阻塞 wait()[必须有锁]/释放锁 run()结束 blocked 结束
第十一讲: 多线程
public class Producer implements Runnable { private SyncStack theStack; private int num; private static int counter = 1; public Producer (SyncStack s) { theStack = s; num = counter++; }
第十一章 多线程
一般当最后一个线程结束时,Java程序才退出 守护线程的存在不影响Java程序的退出 – setDaemon(true) – 使线程成为守护线程(必须在start之前调用) – setDaemon(false) – 使线程成为一般线程(必须在start之前调用) 守护线程一般不能用于执行关键任务 – 任务未执行完,线程就可能被强制结束 守护线程一般用来做辅助性工作 – 提示,帮助等
9
练习
使用Thread 创建线程,并在线程中打印1 到10的整数 将程序改为实现Runnable 接口,实现同样 的功能
10
线程的状态转换
11
线程状态控制 sleep()方法
静态方法,使当前线程休眠。 TestSleep.java
12
线程状态控制 join()方法
合并某个线程。 TestJoin.java
21
死锁
哲学家进餐的问题 两个线程同时等待对方释放一个锁 通过如下方法可以避免: 决定获得锁的顺序 始终坚持这个顺序 倒序释放锁 PhilosopherEat.java
22
线程状态控制 wait 和 notify
场景 设想你和出租车司机代表两个线程 问题: 如何决定何时你到达目的地 方案: 你上车的时候告诉司机你的目的地,然后休息 司机负责开车和到达目的地的时候通知你下车。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
上述的两个例子称为并发 (Concurrent) 程序,前一种并发由操 作系统实现,而后一种并发通常以多线程 (Multi-threading) 方 式实现。
通常情况下,多个进程间不能 (也不应) 相互访问,除非通过操作系统或某些 特定的通信管道 (如系统剪贴板、文件、网络连接等)。从系统资源的角度看 ,每个进程都占据着一段专属于自身的内存空间,其他进程无权访问。相比 之下,同属于一个进程的多个线程却可以共享该进程的内存空间,这也是多 任务与多线程最大的区别所在。
11.1 概述
➢ 线程状态及调度
1. 线程的状态 与对象一样,线程也具有生命周期。
① 新建:线程被创建后所处的状态。
② 可运行:此时的线程有资格运行,但线程调度程序尚未将其选定以进入运 行状态。所有处于可运行状态的线程组成了一个集合——可运行线程池。
③ 运行:线程调度程序从可运行池中选定一个线程并运行,该线程即进入运 行状态。运行中的线程可以回到可运行状态,也可以进入阻塞状态。
④ 阻塞:处于阻塞状态的线程并未终结,只是由于某些限制而暂停了。当特 定事件发生时,处于阻塞状态的线程可以重新回到可运行状态。
⑤ 终结:线程运行完毕后便处于终结状态,此后不能再回到可运行状态。
11.1 概述
➢ 线程状态及调度
2. 线程的调度 当多个线程处于可运行状态时,它们进入可运行线程池排队等待CPU为其服 务。依据一定的原则(如先到先服务),从可运行线程池中选定一个线程并 运行,这就是线程的调度。
线程调度一般由操作系统中的线程调度程序负责,对于Java程序,则由Java 虚拟机负责。
11.1 概述
➢ 线程状态及调度
线程调度的模型有两种——分时模型和抢占模型: ① 分时模型:所有线程轮流获得CPU的使用权,每个线程只能在指定的时间 内享受CPU的服务,一旦时间到达,就必须将CPU的使用权让给另一个线程 。分时模型下,线程并不会主动让出CPU。
11.1 概述
➢ 程序、进程与线程
1. 程序(Program) 程序是指令与数据的集合,通常以文件的形式存放在外存中,也就是说,程序是 静态的代码,其可以脱离于计算机而存在——例如,存储在U盘中的程序。
2. 进程(Process) 进程就是运行中的程序,有时也称为任务 (Task)。操作系统运行程序的过程即是 进程从创建、存活到消亡的过程。
单CPU的机器支持多进程和多线程是从宏观 (用户) 角度来看的,从微观 (CPU) 角度看,多个进程仍然是以串行的方式执行的——即所谓的“微观串 行,宏观并行”。
11.1 概述
➢ 多任务与多线程
严格来说,只有那些具有多个CPU的机器才支持真正意义上的并发。对于那 些计算密集型的程序 (即程序执行时间主要耗费在CPU运算上,如计算圆周 率小数点后一百万位、大矩阵相乘等),将程序编写为多个线程并将它们分 派到各个CPU上并发执行,将大大缩短计算时间。
11.1 概述
➢ 多任务与多线程
多任务是指操作系统中同时运行着多个进程,因此有时也称为多进程。
多线程则是指同一进程中的某些控制流程被多个线程同时执行。
多任务与多线程是并发在不同级别的体现——前者是进程级别,而后者则是 线程级别。
换句话说,多任务是站在操作系统的角度来看并发,而多线程则是站在进程 的角度来看并发。
② 抢占式模型:线程调度程序根据线程的优先级(Priority)来分配CPU的服 务时间,优先级较高的线程将获得更多的服务时间。抢占模型下,线程可以 主动让出CPU的使用权,以使那些优先级较低的线程有机会运行。
显然,抢占模型比分时模型更加灵活,允许编程者控制更多的细节,Java采 用了抢占式线程调度模型。
需要注意,Java虚拟机调度线程的准确时机是无法预期的。因此,编程时不 要对多个线程的执行顺序做任何假设——特别是对那些优先级相近的多个线 程。
JAVA语言程序设计
第11章 多线程与并发
11.1 概述 11.2 线程状态控制 11.3 案例实践11:数字秒表 11.4 并发控制 11.5 案例实践12:生产者与消费者问题
11.1 概述
现代操作系统均支持多任务 (Multi-tasking),即同一时刻可以执 行多个程序。例如,在用Word编辑文档的同时,播放器在播放 音乐、下载程序在下载文件等。
无论多任务还是多线程,它们通常能缩短完成某些(或某项)任务的时间, 从而提高了系统资源的利用率。
11.1 概述
➢ 多任务与多线程
从理论上说,CPU在任一时刻只能执行一条指令,那么,为什么那些只具有 一个CPU 的机器也支持并发呢? 1、不是所有的进程在任一时刻都需要使用到CPU资源。例如,CPU在执行某 个进程的同时,另一个进程可能正在访问I/O设备,此时的两个进程完全可 以同时执行。 2、操作系统让CPU交替执行这些进程。当多个进程同时需要CPU为自己服务 时,操作系统会依据某种选择策略让CPU选择其中一个执行,并在很短的一 段时间后切换到另一个进程执行,如此下去。
11.1 概述
➢ 程序、进程与线程
3. 线程(Thread) 线程是进程中能够独立执行的实体 (即控制流程),是CPU调度和分派的基本 单位。线程是进程的组成部分——进程允许包含多个同时执行的线程,这些 线程共享进程占据的内存空间和其他系统资源。可见,线程的“粒度”较进 程更小,在多个线程间切换所致的系统资源开销要比在多个进程间切换的开 销小得多,因此,线程也称为轻量级的进程。
进程与程序的区别主要体现在: (1) 进程不能脱离于计算机而存在,处于存活状态 (即运行中) 的进程会占用某些 系统资源,如CPU时间、内存空间、外设访问权等,而程序仅占据外存。 (2) 进程是动态的代码,若不运行程序,则操作系统不会创建相应的进程。此外 , 可 以 创 建 同 一 个 程 序 的 多 个 进 程 。 例 如 , 在 Windows 中 同 时 运 行 多 次 notepad.exe,任务管理器中将出现多个名为“记事本”的进程。 (3) 进程消亡时就不存在了,而对应的程序仍然存在。