进程 & 线程 多进程 & 多线程


参考链接

【python 多线程和多进程】说说进程和线程的区别

多线程考点

多线程-并行和并发总结

一文看懂Python多进程与多线程编程(工作学习面试必读)

进程

  • 进程:具有独立功能的程序关于某个数据集合上的一次运行活动
  • 进程有自己的 独立地址空间
    • 每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段
  • 资源分配 的基本单位,它是程序执行时的一个 实例
    • 资源:CPU、内存等
  • 程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行
  • 每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵

线程

  • 线程:在这里插入图片描述

  • CPU调度和分派的基本单位, 程序执行的 最小单位,它是进程的一个执行流

  • 共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多

    • 每个线程有自己的堆栈和局部变量
  • 线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据

  • 线程是在同一时间需要完成多项任务的时候实现的

进程 & 线程

  • 一个进程可以由很多个线程组成

  • 线程间共享进程的所有资源

  • 【基本区别】

    • 线程是处理器调度的基本单位,但是进程不是
  • 【地址空间】

    • 进程有自己的独立地址空间

      • 每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段
    • 线程是共享进程中的数据的,使用相同的地址空间

  • 【资源拥有】

    • 同一进程内的线程共享本进程的资源如内存、I/O、cpu 等

    • 进程之间的资源是独立的

  • 【执行过程】

    • 每个独立的进程程有一个程序运行的入口、顺序执行序列和程序入口
    • 但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制
  • 【性能】

    • 进程切换时,消耗的资源大,效率高
    • 涉及到频繁的切换时,使用线程要好于进程
    • 如果要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程
  • 线程之间的 【通信】更方便

    • 同一进程下的线程共享全局变量、静态变量等数据
    • 进程之间的通信需要以通信的方式(IPC)进行
  • 【健壮性】

    • 一个进程崩溃后,在保护模式下不会对其他进程产生影响
    • 但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮

多线程

处理多线程(独占)

  • mutex(互斥锁)semaphore的一种特殊情况(n=1时)
    • 也就是说,完全可以用后者替代前者
    • 但是,因为mutex 较为简单,且效率高,所以在必须保证资源独占的情况下,还是采用这种设计

JAVA多线程实现的三种方式

  • 继承Thread类实现多线程

    	public class MyThread extends Thread {
    	  public void run() {
    	   System.out.println("MyThread.run()");
    	  }
    	}
    
    	MyThread myThread1 = new MyThread();
    	myThread2.start();
    
  • 实现Runnable接口方式实现多线程

    public class MyThread implements Runnable {
      public void run() {
          System.out.println("MyThread.run()");
      }
        
        public static void main(String[] args) {
            MyThread myThread = new MyThread();
            Thread thread = new Thread(myThread);
            thread.start();        
        }
    }
    
    public class Thread implements Runnable {
        private Runnable target;
        public void run() {
            if (target != null) {
                target.run();
            }
       }
         ...
    }
    
  • 前面两种可以归结为一类

    • 无返回值,原因很简单,通过重写run方法,run方式的返回值是void,所以没有办法返回结果
  • 通过Callable和FutureTask创建线程

    public class CallableFutureTest implements Callable<Integer>{
        
       private int i;
       @Override
       public Integer call(){
         for (i = 0; i < 2; i++) {
           System.out.println("接口创建线程: " + Thread.currentThread().getName() + " : " + i);
       	 }
            return i;
       }
    }
    
    public static void main(String[] args) {
       System.out.println("main线程:" +Thread.currentThread().getName());
        
       long begin = System.currentTimeMillis();
       ExecutorService executorService = Executors.newCachedThreadPool();
        
       //创建了实例
       CallableFutureTest callableFutureTest = new CallableFutureTest();
       //使用FutureTask类包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值
       FutureTask<Integer> futureTask = new FutureTask<>(callableFutureTest); 
       //使用FutureTask对象作为Thread对象的target创建并通过线程对象的start()方法启动线程
       executorService.submit(futureTask);
       try {
                System.out.println("futureTask1: "+ futureTask1.get()} catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                executorService.shutdown();
            }
    	    System.out.println("executor pool: " + executorService.isShutdown());
            System.out.println("time: " + (System.currentTimeMillis() - begin));   
        }
    }
    
  • 通过线程池创建线程

  • 后面两种可以归结成一类

    • 有返回值,通过Callable接口,就要实现call方法,这个方法的返回值是Object,所以返回的结果可以放在Object对象中
三种实现方式的区别
  • 返回值

    • 继承Thread类,run()方法没有返回值
    • 实现Runnable接口和Callable接口方式基本相同
      • 但Callable接口定义的call()方法具有返回值,可以声明抛出异常
  • 继承

    • 继承Thread类,不能再继承其他类
    • 线程类实现Runnable和Callable接口可以继承其他类
  • 访问当前线程

    • 继承Thread类,需访问当前线程,无须用Thread.currentThread()方法,直接使用this即可获得当前线程
    • 线程类实现Runnable和Callable接口
      • 若访问当前线程,必须使用Thread.currentThread()方法
      • 多个线程共享同一个target对象,适合多个相同线程来处理同一份资源的情况,从而将CPU、代码和数据分开,形成清晰的模型,较好地体现面向对象思想

JAVA多线程使用场景

参考链接

JAVA多线程使用场景和注意事项

Java:多线程:到底什么时候该用多线程

  • 高并发
    • 系统接受实现多用户多请求的高并发时,通过多线程来实现
  • 线程后台处理大任务
    • 一个程序是线性执行的,如果程序执行到要花大量时间处理的任务时,那主程序就得等待其执行完才能继续执行下面的。那用户就不得不等待它执行完
    • 这时候可以开线程把花大量时间处理的任务放在线程处理,这样线程在后台处理时,主程序也可以继续执行下去,用户就不需要等待。线程执行完后执行回调函数。
  • 大任务
    • 大任务处理起来比较耗时,这时候可以起到多个线程并行加快处理(例如:分片上传)

多进程 & 多线程

  • 多进程和多线程编程对于代码的并发执行,提升代码效率和缩短运行时间至关重要

  • 多进程的程序要比多线程的程序健壮

    • 一个线程死掉就等于整个进程死掉
  • 【健壮性】多进程要比多线程健壮

    • 一个进程崩溃后,在保护模式下不会对其他进程产生影响
    • 一个线程崩溃整个进程都死掉
  • 【并发性】

    • 进程之间可以并发执行
    • 同一个进程的多个线程之间也可并发执行
  • 【作用】

    • 多进程作用是提高CPU的使用率,而不是提高执行速度
    • 多线程作用是提高应用程序的使用率,而不是提高执行速率

在这里插入图片描述

多CPU,多核,多进程,多线程

多CPU,多核,多进程,多线程

1、单CPU中进程只能是并发,多CPU计算机中进程可以并行。

2、单CPU单核中线程只能并发,单CPU多核中线程可以并行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值