进程与线程

it2025-02-25  30

进程

执行中的程序叫做执行中的程序叫做进程(Process),是一个动态的概念。 为了使计算机程序得以运行,计算机需要加载代码,同 时也要加载数据。

进程是程序的一次动态执行过程, 占用特定的地址空 间。每个进程由3部分组成:cpu,data,code。每个进程都是独立的,保有自己的cpu时间,代码和数据,即便用同一份程序产生好几个进程,它们之间还是拥有自己的这3样东西。 多任务(Multitasking)操作系统将CPU时间动态地划分给每个进程,操作系统同时执行多个进程,每个进程独立运行。以进程的观点来看,它会以为自己独占 Cpu的使用权执行中的程序叫做进程(Process),是一个动态的概念。 为了使计算机程序得以运行,计算机需要加载代码,同时也要加载数据。

线程

线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流, 一个进程中可以并发多个线程,每条线程并行执行不同的任务。

一个进程可拥有多个并行的(concurrent)线程一个进程中的线程共享相同的内存单元/内存地址空 间可以访问相同的变量和对象,而且它们从同一堆中 分配对象通信、数据交换、同步操作由于线程间的通信是在同一地址空间上进行的,所以不需要额外的通信机制,这就使得通信更简便而且信 息传递的速度也更快。

程序是指令的集合,代码的集合;而进程是动态的概念,当程序在执行时,系统分配进程;多线程是在同一 进程下,充分利用资源 ,多条执行路径,共享资源 (cpu data code)。

区别进程线程根本区别作为资源分配的单位调度和执行的单位开销每个进程都有独立的 代码和数据空间(进 程上下文),进程间 的切换会有较大的开 销线程可以看做轻量级的 进程,同一类线程共享 代码和数据空间,每个 线程有独立运行栈和程 序计数器(PC),线程 切换的开销小所处环境在操作系统中能同时 运行多个任务(程 序)在同一应用程序中有多个顺序流同时执行分配内存系统在运行的时候会 为每个进程分配不同 的内存区域线程间共享进程的所有 资源,每个线程只有有 自己的堆栈和局部变 量。线程由CPU独立调 度执行,在多CPU环境 下就允许多个线程同时 运行包 含 关 系没有线程的进程可以看作单线程,如果一 个进程拥有多个线程,则执行过程不是 一条线的,而是多条线(线程)共同完成的线程是进程的一部分,所以线程有的时候会被称为是轻量级进程或轻权进程

多线程的优点:

资源利用率更好; 程序设计在某些情况下更简单; 程序响应更快

多线程的缺点:

设计更复杂,虽然有一些多线程应用程序比单线程的 应用程序要简单,但其他的一般都更复杂。在多线程访问共享数据的时候,这部分代码需要特别的注意。 线程之间的交互往往非常复杂。不正确的线程同步产生的错误非常难以被发现,并且重现以修复。 上下文切换的开销 当 CPU 从执行一个线程切换到执 行另外一个线程的时候,它需要 先存储当前线程的本 地的数据,程序 指针等,然后载入另一个线程的本地 数据,程序指针 等,最后才开始执行。这种切换称 为“上下文切 换”(“context switch”)。CPU 会在一 个上 下文中执行一个线程,然后切换到另外一个上下文中 执 行另外一个线程。上下文切换 并不廉价。如果没 有必要,应该减少上下文切换的发生。

线程的五种状态:

新建状态 就绪状态 运行状态 阻塞状态 死亡状态

新建状态: 使用 new 关键字和 Thread 类或其子类建立一个线程 对象后,该线程对象就处于新建状态。它保持这个状 态直到程序 start() 这个线程。就绪状态:当线程对象调用了start()方法之后,该线程就进入就 绪状态。就绪状态的线程处于就绪队列中,要等待 JVM里线程调度器的调度。运行状态: 如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线 程最为复杂,它可以变为阻塞状态、就绪状态和死亡 状态。阻塞状态:如果一个线程执行了sleep(睡眠)、suspend(挂 起)等方法,失去所占用资源之后,该线程就从运行 状态进入阻塞状态。在睡眠时间已到或获得设备资源 后可以重新进入就绪状态。可以分为三种: 等待阻塞:运行状态中的线程执行 wait() 方法, 使线程进入到等待阻塞状态。 同步阻塞:线程在获取 synchronized同步锁失败 (因为同步锁被其他线程占用)。 其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O请求时,线程就会进入到阻塞状态。当 sleep() 状态超时,join() 等待线程终止或超时,或 者 I/O 处理完毕,线程重新转入就绪状态。 死亡状态: 一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

使线程进入阻塞状态的方法:

sleep方法:sleep() 方法需要指定等待的时间,它可 以让当前正在执行的线程在指定的时间内暂停执行, 进入阻塞状态,该方法既可以让其他同优先级或者高 优先级的线程得到执行的机会,也可以让低优先级的 线程得到执行机会。但是 sleep() 方法不会释放“锁标志”,也就是说如果有 synchronized 同步块,其他线 程仍然不能访问共享数据。yield方法: yield() 方法和 sleep() 方法类似,也不会释 放“锁标志”,区别在于它没有参数,即 yield() 方法 只是使当前线程重新回到可执行状态,所以执行 yield() 的线程有可能在进入到可执行状态后马上又被执行。让出CPU的使用权,从运行态直接进入就绪态。让CPU重新挑选哪一个线程进入运行状态。join方法: 方法会使当前线程等待调用 join() 方法的线程执行结束之后,才会继续往后执行

join方法的实例:

package com.ysh.demo.review04; public class DohomeworkDemoTest01 { public static void main(String[] args) { new Thread(new Teacher()).start(); } } class Teacher implements Runnable{ @Override public void run() { System.out.println("老师来了,开始上课"); System.out.println("今天开始测试"); System.out.println("测试的内容是.........."); System.out.println("测试时间是120分钟"); Thread thread=new Thread(new Student()); thread.start(); //开启学生线程 try { thread.join(); //插队 //如果join()方法里面没有参数,表示永远都会等待另一个线程结束完,然后再执行其它线程,但是如果加入参数的话,则表示thread线程只能插队传入的参数毫秒 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("还有30分钟"); System.out.println("考试结束"); } } class Student implements Runnable{ @Override public void run() { System.out.println("学生拿到试卷,开始答题"); System.out.println("学生抓脑"); System.out.println("唉,考试题目真变态"); } }

yield的实例:

package com.ysh.demo.review04; public class ThreadYieldTest implements Runnable{ public static void main(String[] args) { ThreadYieldTest tyl=new ThreadYieldTest(); Thread th=new Thread(tyl,"我是A"); Thread th2=new Thread(tyl,"我是B"); th.start(); Thread.yield(); th2.start(); } @Override public void run() { System.out.println(Thread.currentThread().getName()+"哈哈哈"); System.out.println(Thread.currentThread().getName()+"噢噢噢噢"); } }

Thread中常用方法:

常用方法功能isAlive()判断线程是否还"活"着,即线程是否还未终止getPriority()获得线程的优先级数值setPriority设置线程的优先级数值(线程的优先级是1-10)setName()给线程设置名字getName()获取线程的名字currentThread()(静态方法)获取当前正在运行的线程对象

Thread线程中的三个常量:

MIN_PRIORITYMAX_PRIORITYNORM_PRIORITY1105

线程同步(synchronized):

线程同步:即当有一个线程在对内存进行操作时,其他 线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态。 同步就是协同步调,按预定的先后次序进行运行。如: 你说完,我再说。

死锁:

死锁是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的线程称为死锁线程。

//口红 class Lipstick{ } // 镜子 class Mirror{ } class Makeup extends Thread { int flag; String girl; static Lipstick lipstick=new Lipstick(); static Mirror mirror= new Mirror(); @Override public void run() { // TODO Auto-generated method stub doMakeup(); } void doMakeup(){ if(flag==0){ synchronized (mirror) { System.out.println(girl+"拿着镜 子!"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lipstick) { System.out.println(girl+"拿着口红!"); } } }else{ synchronized (lipstick) { System.out.println(girl + "拿着口 红!"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (mirror) { System.out.println(girl + "拿着镜子!"); } } } } } public class TestDeadLock { public static void main(String[] args) { Makeup m1 = new Makeup(); m1.girl="大 丫"; m1.flag=0; Makeup m2 = new Makeup(); m2.girl="小 丫"; m2.flag=1; m1.start(); m2.start(); } }
最新回复(0)