进程与线程

进程

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

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

线程

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

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

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

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

多线程的优点:

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

多线程的缺点:

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

线程的五种状态:

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

在这里插入图片描述

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

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

  • 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_PRIORITY
1105

线程同步(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();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值