1.多进程
——————系统资源分配和调度的独立单位
进程:正在运行的程序
- 系统资源分配和调度的独立单位
- 每一个进程都有他自己的内存空间和系统资源
多进程的缺点:
多进程与多线程共同点:均支持并发,均需要调度,由调度优先级控制。
创建一个线程
Java 提供了三种创建线程的方法:
- 通过实现 Runnable 接口;
- 通过继承 Thread 类本身;
-
线程的生命周期
线程的状态
新建状态:使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
就绪状态:当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
运行状态:如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和终止状态。
阻塞状态:如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种: 等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
- 同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
- 其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
终止状态:一个运行状态的线程完成任务或者其他终止条件发生时【run( )结束或stop( )】,该线程就切换到终止状态。
线程调度:
- 分时调度:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。
- 抢占式调度:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性)
在抢占模式下,操作系统负责分配CPU时间给各个进程,一旦当前的进程使用完分配给自己的CPU时间,操作系统将决定下一个占用CPU时间的是哪一个线程。因此操作系统将定期的中断当前正在执行的线程,将CPU分配给在等待队列的下一个线程。所以任何一个线程都不能独占CPU。每个线程占用CPU的时间取决于进程和操作系统。进程分配给每个线程的时间很短,以至于我们感觉所有的线程是同时执行的。实际上,系统运行每个进程的时间有2毫秒,然后调度其他的线程,它同时维持着所有的线程和循环,分配很少量的CPU时间给线程。
调度是什么意思?调度意味着处理器存储着将要执行完CPU时间的进程的状态和将来某个时间装载这个进程的状态而恢其运行。(包括抢到CPU执行权和其他线程抢到执行权)
大部分操作系统都支持多进程并发运行,现在的操作系统几乎都支持同时运行多个程序。比如:现在我们上课一边使用编辑器,一边使用录屏软件,同时还开着画图板,dos窗口等软件。此时,这些程序是在同时运行,”感觉这些软件好像在同一时刻运行着“。
实际上,CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换。对于CPU的一个核而言,某个时刻,只能执行一个线程,而 CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是在同一时刻运行。
其实,多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的使用率更高。
抢占式有不足之处,一个线程可以在任何给定的时间中断另外一个线程的执行。假设一个线程正在向一个文件做写入操作,而另外一个线程中断其运行,也向同一个文件做写操作,就会出现写入问题。
Java采用抢占式调度策略
- 每个线程分配一个线程优先级,优先级高的线程优先调度。
- 优先级相同的,根据在等待队列的排列顺序按“先到先服务”原则调度。
- 每个线程有一个时间片,时间片用完轮到下一线程。
- 下面几种情况下,当前线程会放弃CPU:
(1)当前时间片用完;
(2)线程在执行时调用了yield() 或sleep() 方法主动放弃;
(3)进行I/O 访问,等待用户输入,导致线程阻塞;或者为等候一个条件变量,线程调用wait()方法;
(4)有高优先级的线程参与调度。
线程的优先级用数字来表示,范围从1~10。主线程的默认优先级为5
- Thread.MIN_PRIORITY=1
- Thread.MAX_PRIORITY=10
- Thread.NORM_PRIORITY=5
【注意】优先级高,仅仅表示获取CPU的时间片的几率高,但是在次数较多时或者多次运行才能看到想要的结果,线程优先级不能保证线程执行的顺序,而且非常依赖于平台。
Thread 类中设置和获取线程优先级的方法
setPriority(int)设置线程优先级;public final void setPriority( int newPriority) 【MIN_PRIORITY<=setPriority<=MAX_PRIORITY】
getPriority()获取线程优先级。public final int getPriority()