美文网首页
进程与线程,并发与并行简单理解

进程与线程,并发与并行简单理解

作者: 梧叶已秋声 | 来源:发表于2020-08-20 09:36 被阅读0次

这里不管进程与线程的概念,先看看进程与线程的使用。
现有代码如下,内含加法和减法函数,程序运行时按顺序调用加法和减法函数。

public class MainActivity extends AppCompatActivity{
    private static final String TAG = "MainActivity";
    private int mInt1 = 10;
    private int mInt2 = 5;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG,"add result " + add(mInt1,mInt2));
        Log.d(TAG,"subtract result " + subtract(mInt1,mInt2));

    }

    private int add(int int1,int int2){
        for (int i = 0 ; i < 500 ; i ++){
            Log.d(TAG, "inner add " + i);
        }
        return (int1 + int2);
    }

    private int subtract(int int1,int int2){
        for (int i = 0 ; i < 500 ; i ++){
            Log.d(TAG, "inner subtract " + i);
        }
        return (int1 - int2);
    }

}

运行程序(即打开app)后如下所示。

2020-08-17 16:16:50.620 11449-11449/com.example.myapplication D/MainActivity: inner add 0
2020-08-17 16:16:50.621 11449-11449/com.example.myapplication D/MainActivity: inner add 1
2020-08-17 16:16:50.621 11449-11449/com.example.myapplication D/MainActivity: inner add 2
2020-08-17 16:16:50.621 11449-11449/com.example.myapplication D/MainActivity: inner add 3
2020-08-17 16:16:50.621 11449-11449/com.example.myapplication D/MainActivity: inner add 4
2020-08-17 16:16:50.621 11449-11449/com.example.myapplication D/MainActivity: inner add 5
2020-08-17 16:16:50.621 11449-11449/com.example.myapplication D/MainActivity: inner add 6
2020-08-17 16:16:50.621 11449-11449/com.example.myapplication D/MainActivity: inner add 7
............................
2020-08-17 16:16:50.635 11449-11449/com.example.myapplication D/MainActivity: add result 15
2020-08-17 16:16:50.635 11449-11449/com.example.myapplication D/MainActivity: inner subtract 0
2020-08-17 16:16:50.635 11449-11449/com.example.myapplication D/MainActivity: inner subtract 1
2020-08-17 16:16:50.635 11449-11449/com.example.myapplication D/MainActivity: inner subtract 2
2020-08-17 16:16:50.635 11449-11449/com.example.myapplication D/MainActivity: inner subtract 3
2020-08-17 16:16:50.635 11449-11449/com.example.myapplication D/MainActivity: inner subtract 4
............................
2020-08-17 16:16:50.651 11449-11449/com.example.myapplication D/MainActivity: inner subtract 494
2020-08-17 16:16:50.651 11449-11449/com.example.myapplication D/MainActivity: inner subtract 495
2020-08-17 16:16:50.651 11449-11449/com.example.myapplication D/MainActivity: inner subtract 496
2020-08-17 16:16:50.651 11449-11449/com.example.myapplication D/MainActivity: inner subtract 497
2020-08-17 16:16:50.651 11449-11449/com.example.myapplication D/MainActivity: inner subtract 498
2020-08-17 16:16:50.652 11449-11449/com.example.myapplication D/MainActivity: inner subtract 499
2020-08-17 16:16:50.652 11449-11449/com.example.myapplication D/MainActivity: subtract result 5

运行时间从16:16:50.62016:16:50.652,所需时间为0.032s。

现将程序简单修改,引入线程。

public class MainActivity extends AppCompatActivity{
    private static final String TAG = "MainActivity";
    private int mInt1 = 10;
    private int mInt2 = 5;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG,"add result " + add(mInt1,mInt2));
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG,"subtract result " + subtract(mInt1,mInt2));
            }
        }).start();
    }

    private int add(int int1,int int2){
        for (int i = 0 ; i < 500 ; i ++){
            Log.d(TAG, "inner add " + i);
        }
        return (int1 + int2);
    }

    private int subtract(int int1,int int2){
        for (int i = 0 ; i < 500 ; i ++){
            Log.d(TAG, "inner subtract " + i);
        }
        return (int1 - int2);
    }

  }

最后log如下所示(不同设备可能运行结果略微不一样,但是总归是轮流调用add和subtract函数)。

2020-08-17 16:21:28.546 11828-11847/com.example.myapplication D/MainActivity: inner add 0
2020-08-17 16:21:28.546 11828-11847/com.example.myapplication D/MainActivity: inner add 1
2020-08-17 16:21:28.546 11828-11847/com.example.myapplication D/MainActivity: inner add 2
2020-08-17 16:21:28.546 11828-11847/com.example.myapplication D/MainActivity: inner add 3
2020-08-17 16:21:28.546 11828-11848/com.example.myapplication D/MainActivity: inner subtract 0
2020-08-17 16:21:28.546 11828-11847/com.example.myapplication D/MainActivity: inner add 4
2020-08-17 16:21:28.546 11828-11848/com.example.myapplication D/MainActivity: inner subtract 1
2020-08-17 16:21:28.546 11828-11847/com.example.myapplication D/MainActivity: inner add 5
...................................................
2020-08-17 16:21:28.559 11828-11847/com.example.myapplication D/MainActivity: inner add 498
2020-08-17 16:21:28.559 11828-11848/com.example.myapplication D/MainActivity: inner subtract 496
2020-08-17 16:21:28.559 11828-11847/com.example.myapplication D/MainActivity: inner add 499
2020-08-17 16:21:28.559 11828-11848/com.example.myapplication D/MainActivity: inner subtract 497
2020-08-17 16:21:28.559 11828-11847/com.example.myapplication D/MainActivity: add result 15
2020-08-17 16:21:28.559 11828-11848/com.example.myapplication D/MainActivity: inner subtract 498
2020-08-17 16:21:28.559 11828-11848/com.example.myapplication D/MainActivity: inner subtract 499
2020-08-17 16:21:28.559 11828-11848/com.example.myapplication D/MainActivity: subtract result 5

运行时间从16:21:28.546到16:21:28.559,所需时间为0.013s。

由此可以看出,在输出同样的日志的情况下,引入线程后,耗时减少了。

而所谓进程,是程序的一次执行,这里可以理解为app的一次打开,即一次执行。
进程通常由程序、数据和进程控制块(Process Control Block,PCB)组成。
1.进程控制块。进程控制块是进程存在的唯一标志。

《软件设计师教程》

这里我只看看进程标识符。
进程标识符就是PID,每个应用在打开后,系统会给app分配一个标识符。

cmd进入控制台。

adb shell
ps 
image.png

显示当前所有进程,打开app后,输入ps |grep + 包名。

ps |grep com.example
u0_a119   29441 759   1678764 45676 SyS_epoll_ 0000000000 S com.example.myapplication

出处:Android 查看进程ID(PID)比较进程优先级
各列参数意义:
USER 进程当前用户;
PID Process ID,进程ID;
PPID Process Parent ID,进程的父进程ID;
VSIZE Virtual Size,进程的虚拟内存大小;
RSS Resident Set Size,实际驻留”在内存中”的内存大小;
WCHAN 休眠进程在内核中的地址;
PC Program Counter;
NAME 进程名;

2.程序
程序部分描述了进程需要完成的功能。我这里的demo就是加减数据的功能。
3.数据
数据部分包括程序执行时所需的数据及工作区。
这里涉及到程序执行时数据的存储。
一个可执行文件运行起来的话它就变成了进程,然后系统会给进程分配一个4G大小的虚拟地址空间。其中前3G内存是用户空间,最后1G是内核空间。所有的进程有各自的用户空间,但所有的进程都共享一个内核空间。

https://blog.csdn.net/czc1997/article/details/81159126

线程:

出处:《软件设计师教程》
传统的进程有两个基本属性: 可拥有资源的独立单位;可独立调度和分配的基本单位。由于在进程的创建、撤销和切换中, 系统必须为之付出较大的时空开销, 因此在系统中设置的进程数目不宜过多, 进程切换的频率不宜太高, 这就限制了并发程度的提高。引入线程后, 将传统进程的两个基本属性分开,线程作为调度和分配的基本单位,进程作为独立分配资源的单位。用户可以通过创建线程来完成任务, 以减少程序并发执行时付出的时空开销。

进程与线程的定义为:

线程作为调度和分配的基本单位,进程作为独立分配资源的单位。用户可以通过创建线程来完成任务, 以减少程序并发执行时付出的时空开销。

现在来看并发与并行。

并发(concurrency)和并行(parallelism)的区别
并发性(concurrency),又称共行性,是指能处理多个同时性活动的能力,并发事件之间不一定要同一时刻发生。
并行(parallelism)是指同时发生的两个并发事件,具有并发的含义,而并发则不一定并行。

将代码稍微修改,执行减法之前先休眠。

        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG,"add result " + add(mInt1,mInt2));
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.currentThread().sleep(1);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                Log.d(TAG,"subtract result " + subtract(mInt1,mInt2));
            }
        }).start();
2020-08-17 16:41:31.668 14006-14032/com.example.myapplication D/MainActivity: inner add 0
2020-08-17 16:41:31.668 14006-14032/com.example.myapplication D/MainActivity: inner add 1
2020-08-17 16:41:31.668 14006-14032/com.example.myapplication D/MainActivity: inner add 2
2020-08-17 16:41:31.668 14006-14032/com.example.myapplication D/MainActivity: inner add 3
2020-08-17 16:41:31.668 14006-14032/com.example.myapplication D/MainActivity: inner add 4
2020-08-17 16:41:31.668 14006-14032/com.example.myapplication D/MainActivity: inner add 5
2020-08-17 16:41:31.668 14006-14032/com.example.myapplication D/MainActivity: inner add 6
2020-08-17 16:41:31.668 14006-14032/com.example.myapplication D/MainActivity: inner add 7
2020-08-17 16:41:31.668 14006-14032/com.example.myapplication D/MainActivity: inner add 8
2020-08-17 16:41:31.668 14006-14032/com.example.myapplication D/MainActivity: inner add 9
2020-08-17 16:41:31.668 14006-14032/com.example.myapplication D/MainActivity: inner add 10
2020-08-17 16:41:31.668 14006-14032/com.example.myapplication D/MainActivity: inner add 11
2020-08-17 16:41:31.668 14006-14032/com.example.myapplication D/MainActivity: inner add 12
................................
2020-08-17 16:41:31.669 14006-14032/com.example.myapplication D/MainActivity: inner add 49
2020-08-17 16:41:31.669 14006-14033/com.example.myapplication D/MainActivity: inner subtract 0
2020-08-17 16:41:31.669 14006-14032/com.example.myapplication D/MainActivity: inner add 50
2020-08-17 16:41:31.669 14006-14033/com.example.myapplication D/MainActivity: inner subtract 1
2020-08-17 16:41:31.669 14006-14032/com.example.myapplication D/MainActivity: inner add 51
2020-08-17 16:41:31.669 14006-14033/com.example.myapplication D/MainActivity: inner subtract 2
................................

2020-08-17 16:41:31.682 14006-14032/com.example.myapplication D/MainActivity: inner add 499
2020-08-17 16:41:31.682 14006-14033/com.example.myapplication D/MainActivity: inner subtract 436
2020-08-17 16:41:31.682 14006-14032/com.example.myapplication D/MainActivity: add result 15
2020-08-17 16:41:31.682 14006-14033/com.example.myapplication D/MainActivity: inner subtract 437
2020-08-17 16:41:31.682 14006-14033/com.example.myapplication D/MainActivity: inner subtract 438
................................
2020-08-17 16:41:31.684 14006-14033/com.example.myapplication D/MainActivity: inner subtract 496
2020-08-17 16:41:31.684 14006-14033/com.example.myapplication D/MainActivity: inner subtract 497
2020-08-17 16:41:31.684 14006-14033/com.example.myapplication D/MainActivity: inner subtract 498
2020-08-17 16:41:31.684 14006-14033/com.example.myapplication D/MainActivity: inner subtract 499
2020-08-17 16:41:31.684 14006-14033/com.example.myapplication D/MainActivity: subtract result 5

由于执行加法和减法函数的开始时间不同,16:41:31.668开始打印加法函数中的log,16:41:31.669开始打印减法函数中的log,并且,到16:41:31.669时加函数并未完成,因此此时程序是并发执行,而不是并行执行。
时间轴如下所示。

image.png

如果没有使用延时的情况下,也就是代码如下的情况下。


        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG,"add result " + add(mInt1,mInt2));
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG,"subtract result " + subtract(mInt1,mInt2));
            }
        }).start();
    }

时间轴如下所示。


image.png

log打印开始时间是同一时间,并且同时打印log,因此是程序是并行执行,并且也是并发执行

参考链接:
并发(concurrency)和并行(parallelism)的区别
《软件设计师教程》
Android 查看进程ID(PID)比较进程优先级

相关文章

  • Java 线程相关

    目录1.并行与并发2.进程与线程---- 2.1 进程---- 2.2 线程---- 2.3 进程与线程的区别--...

  • 并发编程之进程与线程

    并发编程之进程与线程 2.1 线程与进程 2.1.1 进程 2.1.2 线程 2.1.3 二者对比 2.2 并行与...

  • iOS 多线程技术总结

    概览 进程与线程的概念 多线程的由来 并行与并发 多线程的实现 串行与并行 线程的几种状态 串行队列与并发队列区别...

  • 进程与线程,并发与并行简单理解

    这里不管进程与线程的概念,先看看进程与线程的使用。现有代码如下,内含加法和减法函数,程序运行时按顺序调用加法和减法...

  • Python(2)---并发编程

    目录 1. Python多线程与多进程知识1.1 并发与并行1.2 线程(thread)与进程(process)...

  • Python3学习笔记:清晰理解协程

    线程和进程 在了解协程之前,我们先简单了解一下进程与线程,并发与并行的概念。 进程:是资源分配的独立单位。我们可以...

  • 并发编程一:线程基础

    一、并行与并发 并发:任务交替执行,看起像在同时进行。并行:任务同时进行。 二、线程与进程 进程是操作系统分配资源...

  • Python多线程与多进程

    内容简述: 线程与进程的相关概念1、程序,进程,线程,多进程,多线程2、线程的生命周期3、并行与并发,同步与异步4...

  • 多线程笔记

    一:基础部分 并发与并行: 进程与线程: 线程调度: Thread.sleep(); //静态方法 可直接使用 ...

  • 进程,线程,并行,并发,python 之 GIL详解

    主要内容:1.线程与进程2.并发与并行3.python GIL 1.进程与线程 进程:程序的一次执行 线程:CPU...

网友评论

      本文标题:进程与线程,并发与并行简单理解

      本文链接:https://www.haomeiwen.com/subject/sgvfjktx.html