进程和线程的详细(概)描述

本文详细介绍了进程与线程的区别,进程的资源分配单元特性,线程作为调度基本单元的特性。阐述了进程的就绪、执行、阻塞、挂起、终止状态以及线程的生命周期,包括新建、运行、阻塞、等待、终止状态。讨论了处理机调度的三个层次以及线程池的概念和作用,强调了线程安全和线程池在多线程并发中的重要性。
摘要由CSDN通过智能技术生成

  1. 1什么是进程?  进程状态指的是什么?  进程阻塞挂起是怎么回事?  进程有什么开发方法?
  2. 什么是线程? 线程有什么状态呢?控制运行又是什么? 线程的优先级是什么意思?  什么是线程安全的呢? 线程和进程有什么区别呢? 
  3. 处理机在执行的时候是如何调度的呢?
  4. 线程池指的什么东西?  ?

解答:

0.进程和线程的区别?
   1.进程是并发程序执行过程中资源分配的基本单元,线程是程序运行与调度的基本单元。

1.进程

1.1打开电脑,CPU工作,登录QQ(这个applation),CPU通过作业调度在内存中分配一定空间让QQ处于(看起来)运行的状态。运行不同的程序需要不同的进程,内存中也是独立的区域。父进程与子进程之间也是独立的,没有资源共享。数据结构集(PCB块)是感知进程存在的唯一实体

1.2 就绪-> 执行-> 阻塞 -> 挂起 -> 终止

就绪:万事俱备只欠东风(CPU资源);

执行:东风来了 开始执行;

阻塞:要等待一下才能继续吹进程因发生某等待事件而无法执行,变为阻塞状态,如发生了I/O请求;(被动,资源完备后依               然受CPU调度进入就绪)

挂起:太猖狂(eg;系统负荷太重,不重要进程被挂起),进程被处理机调度 有内存 进入 外存;(主动,被调离内存,不受                   CPU控制了,需要通过resume()函数再次进入就绪)

    【挂起原因多种,父进程希望挂起某个子进程,进行修改或协调;操作系统需要,检查运行资源;终端用户请求强制暂停等】 

终止:本进程结束,撤销时所有子进程全被PCB的递归删除,否则失控。

注意下图, 没有  阻塞->运行;就绪 -> 阻塞 的可能。



2.1 什么是线程?

(轻型进程),一个进程可以支持多个线程(这些线程可以共享当个进程的内存区域和数据,但是彼此相互独立,可以并发进行)。并发,虽然看起来是同时,但CPU一个时刻只能处理一个子任务,分时OS就采用时间片轮转。

java中,线程的状态使用一个枚举类型来描述的。这个枚举一共有6个值: NEW(新建)、RUNNABLE(运行)、BLOCKED(锁池)、TIMED_WAITING(定时等待)、WAITING(等待)、TERMINATED(终止、结束)。

(YY的挂起状态):一个正在运行的线程有可能会进入I/O交互,还可能调用sleep()方法,还有可能在当前线程当中有其它线程调用了join()方法。这时候线程就进入了阻塞状态(但这也只是人们在理解的时候意淫加上去的,源代码里也没有定义这一个状态)。阻塞状态的线程是没有释放对象锁的。当I/O交互完成,或sleep()方法完成,或其它调用join()方法的线程执行完毕。阻塞状态的线程就会恢复到可运行状态,此时如果再次获得CPU时间片就会进入运行状态。

等待状态-定时等待状态:一个处于运行状态的线程还可能调用wait()方法,或者带时间参数的wait(long milli)方法。如果调用的是不带时间参数的wait(),则需要notify()或notifyAll()这两个方法来唤醒它然后进入锁池状态。进入锁池状态以后继续参与锁的竞争。一个线程如果的调用了带时间参数的wait(long milli)方法进入了定时等待状态,这时候线程就会将对象锁释放,进入等待队列里面,只要时间一到就会进入锁池状态,并不需要notify()或notifyAll()方法来唤醒它。



2.2 线程的运行运行状态:

初始化(new 实例化一个线程对象,暂不分配资源);

可运行状态(通过start()方法,为线程分配除CPU之外的资源,进入 Runnable状态)

运行状态(线程调度,CPU开始处理一个Runnable线程,开始运行 run()函数代码)run(),你调不调度,我一直都在等待。

阻塞状态(正在运行,遇到了I/O请求,然后进入阻塞态,进入阻塞池等待)

4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
Thread.sleep(long millis)方法  Object类中的wait()方法 Thread.yield() 方法 Object类中的notify()方法
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。(wait会释放持有的锁)
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。(注意,sleep是不会释放持有的锁)

调用sleep(n)休眠不会释放对象锁,线程进入暂时休眠n时间;调用join()使线程???,本线程A中调用B.join(),那么本线程暂时阻塞,B执行。直到B线程执行完毕,A,B重新回到并行状态。wait()方法使线程挂起,释放对象锁,进入对象的等待锁定池(回应了wait()方法),直到线程得到notify() 和 notifyAll()消息,线程才会进入“可执行”状态)

join()方法:实现现成的并行->串行的变化。join方法是通过调用线程的wait方法来达到同步的目的的。例如,A线程中调用了B线程的join方法,则相当于A线程调用了B线程的wait方法,在调用了B线程的wait方法后,A线程就会进入阻塞状态。t.join();在t.start()之后才有意义。

public class JoinTest {
    public static void main(String [] args) throws InterruptedException {
        ThreadJoinTest t1 = new ThreadJoinTest("小明");
        ThreadJoinTest t2 = new ThreadJoinTest("小东");
        t1.start();
        /**join方法可以传递参数,join(10)表示main线程会等待t1线程10毫秒(也就是main线程会阻塞状态10ms),串行,10毫秒过去后,
         * main线程和t1线程之间执行顺序由串行执行变为普通的并行执行
         */
        t1.join(10);
        t2.start();
    }

}

挂起状态(暂时淘汰出内存,待资源充足重新调回。??这个不确定   Java2之前的版本,用resume()和suspend() 暂停(而非终止)和再启动线程。stop()是终止线程,终止了不能用suspend恢复。)

1
2
final void suspend( )
final void resume( )
void stop( )
当一个处于运行状态的线程调用了suspend()方法以后,它就会进入挂起状态(这一方法已经过时不建议使用)。挂起状态的线程也没有释放对象锁,它需要调用resume()方法以后才能恢复到可运行状态。将线程挂起容易导致程序死锁

死亡状态(线程dead,原因 线程运行完毕,意外退出,父类线程控制其消亡)


(19)、wait和sleep的区别

sleep()方法,线程不会释放对象锁。导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。

wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备。

2.3 线程的优先级:

    每个线程都有自己的优先级,优先级越高越先被CPU 执行。若未拥有优先级,但出于runnable状态的线程会自动获得优先级。本线程运行时,另一个更高优先级刚好处于runnable状态,本线程暂停 那个被立即执行【先占式调度】。

上下文切换(进程类似):当前线程的任务并没有执行完毕,所以在切换时需要保存本线程的运行状态,以便下次重新切换回来时能够继续切换之前的状态运行。线程上下文切换过程中会记录程序计数器、CPU寄存器状态等数据。

Java线程的优先级用整数表示,取值范围是1~10,Thread类有以下三个静态常量:
[plain]  view plain  copy
  1. static int MAX_PRIORITY  
  2.           线程可以具有的最高优先级,取值为10。  
  3. static int MIN_PRIORITY  
  4.           线程可以具有的最低优先级,取值为1。  
  5. static int NORM_PRIORITY  
  6.           分配给线程的默认优先级,取值为5。  
Thread类的setPriority()和getPriority()方法分别用来设置和获取线程的优先级。
 每个线程都有默认的优先级。主线程的默认优先级为Thread.NORM_PRIORITY。
线程的优先级有继承关系,比如A线程中创建了B线程,那么B将和A具有相同的优先级。

2.4 线程开发,运行控制的几个方法【之后再···说】

1.实现Runnable接口,override?? 实现?? 它的run()方法

2.集成Thread 类,覆盖 它的 run()方法。 Thread 类已经实现了Runnable接口的run()方法,因此是直接覆盖。

   Runnable接口实现  解决了一个很重要的问题:java单一继承的局限性。

2.5 多线程

多线程并发技术。实现方法: 继承Thread类,实现Runnable接口。

2.6 什么是线程安全的?什么是线程不安全?

安全:会有一些线程共同执行一段代码,如果每次执行的结果多线程跟单线程执行结果相同,其他变量也与预期相同,那么认为是线程安全的。

一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。线程安全问题都是由全局变量静态变量引起的。多个线程同时执行写操作的话,一般要考虑同步

举例:比如一个 ArrayList 类,在添加一个元素的时候,它可能会有两步来完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。

单线程时,直接两步。多线程时,线程A先进行1,将元素放到位置0,此时调度A暂停,然后线程B也进行1,将元素放到数组中,因为此时size依旧是0,所以会也位置0 处,A,B运行结束后发现只有位置1有元素,但是size却变成了2,是线程不安全。

不安全:不提供数据访问保护,可能会出现多个线程先后更改数据造成,读出来的是脏数据。(参考前面数据库中S锁,X锁的知识)



3.处理机的调度过程:
对进程的争用,【作业调度(高级调度)、中级调度、进程调度(低级调度)】

1. 作业调度:内外存之间的调度。从外存上处于后备状态的作业挑选一个或多个作业,分配内存,I/O等必要资源,建立相应的进                程,获得竞争处理机的权利。

2. 中级调度:内存调度。为了提高内存利用率和系统吞吐量。对暂时不运行的进程,调至外存等待(进程挂起)。当期具备

              运行件时,重新调入内存,进入就绪态,在就绪队列等待。

3. 进程调度:一般几十ms一次,按一定策略方法,从就绪队列中选取一个进程,认为竞争处理机成功。



4. 线程池的概念:

为什么要用线程池? 

1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程【线程创建和销毁的时间远大于执行的时间】,会很大程度上影响处理效率。线程池       缓存线程,可用已有的闲置线程来执行新任务。

2.限制系统中执行线程的数量(控制最大并发数),太少资源浪费线程并发数量过多(共享系统资源的),抢占系统资源从而导致阻塞率变高。

3.在线程池中,对线程进行一些简单的管理。

Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。4种常见的线程池:

1.newSingleThreadExecutor 单个线程的线程池,即线程池中每次只有一个线程工作,单线程串行执行任务

2.newFixedThreadPool 创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

3.newCacheThreadExecutor(推荐使用)可缓存线程池,当线程池大小超过了处理任务所需的线程,那么就会回收部分空闲(一般是60秒无执行)的线程,当有任务来时,又智能的添加新线程来执行。

4.newScheduledThreadPool 创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求


  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值