对线程、进程和Java线程池的理解

        人生最大的悲哀,莫过于我本可以。

        我钻研操作系统,后选修Linux操作系统,做过父进程生子进程的作业,还做过IO多路复用、多线程的网络游戏,自认为对线程、进程的理解颇深。

        然,多次面试,面对面试官:“你对Java的线程池机制有所了解吗?”

        我不由噤声。

        面试官再问:“你说一说进程与线程的区别。”

        我更是大惊失色,支支吾吾,拾了一些“进程不共享资源”、“进程对应多个线程”、“线程是执行最小单位”、“一个进程至少一个线程”来答,看着面试官越来越失望的脸色,我自知面试必挂。

        苦也!

进程:

        进程是操作系统最重要的四个概念之一,另外三个分别是线程、进程调度、IPC进程通信。

        1.定义:进程是运行中的程序。程序可以认为是一段数据,其没什么意义,只有跑起来才能工作。

        2.1号进程:最初始的进程,所有进程都是基于它的基础上创建的,如果某个进程的父进程结束了,会托管给它。【没错,进程是靠父进程生出来的】

        3.当前工作目录:一个进程的运行,可能需要5、6个变量,而硬盘中可能有几千个变量,如果全部加载进内存,内存不够用,所以得有选择地加载变量。用什么区别变量呢?就是当前工作目录working directory。简单地说,你下载了Java后,为什么要修改系统变量,添加bin目录?明明cmd语句,在java的bin目录下完全可以运行java程序。就是因为,添加进系统变量后,运用起来非常方便,否则你打开IDE,还得自己配置环境变量。

                这是非常重要的概念,命令pwd可以打印出来,在编写程序时,用getcwd也可以得到。【目录的本质也是一个文件,其文件结构是一条一条的,用read读出来能发现其信息包括文件ID、name啥啥啥的】

        4.一些进程举例:除了我们自己写了并运行的进程,操作系统还为我们提供原生进程(也是下载过来的),比如Linux的命令ls,其本质也是一个进程,如果我们在运行结束后,用echo $?命令,打印返回值,甚至能得到一个0。或者cat命令,如果打印一个不存在的文件null,cat  null,然后用echo $?打印返回值,会出现!0(非0)的数。

        5.c语言创建进程:有两步,第一个是fork复制一个子进程,第二步是用exec函数族(一般用execl,比较简单)替换进程。【什么意思呢?我们知道,进程是由父进程生出来的,那么生进程怎么做到?】

                我们知道,fork函数可以创建一个子进程,这个进程和父进程一模一样,从fork语句后执行一样的语句,不过fork的子进程、父进程返回值不一样,返回0的是子进程,!0(非0,子进程ID)的是父进程,就此区别父子进程。

                我们一般用子进程替换成别的进程(当然,替换后它仍然是子进程,关系不会变),用excel函数,提供参数(path, args)即可,举例:

                excel("/usr/bin/ls", "ls");【注意,CMD命令,第一个参数是其自身】

                你写下这行语句,如果将进程运行在后台(用&),就会发现终端竟然打印了当前工作目录下的所有文件。

        6.进程创建消耗的资源:创建一个进程,意味着要给它分配堆栈、数据段的资源。

        7.进程间通信,7种常用方式:套接字socket(没错,就是网络编程的套接字,网络编程实际就是两个进程的通信)、共享内存、消息队列、信号量(常处理并发问题)、信号(ctrl+z杀死进程)、管道、命名管道(区别是命名管道,可用于与父子血缘关系的进程通信)

        8.进程安全性:一个进程的崩溃、销毁、创建,一般不会影响到其它进程的正常生命周期。

        9.进程和线程的关系:一个进程至少对应一个线程,因为进程只是资源分配的最小单元,不是执行的最小单元。

线程:

        1.定义:把它看成一条从上到下的时间线,对于下面的代码段,线程就是a->b->c,我是这么理解的。

a;
b;
c;

        2.线程创建消耗的资源:一般只有堆栈,数据段的资源默认共享。【不过,当出现某些变化时,可能会创建新资源】

        3.C进程的创建:需要使用到pthread库函数,有声明、创建两个基础操作(pthread_t pname; pthread_create(&pname, NULL, 函数名, NULL【变量】);一般函数名运行完毕后线程就会销毁。

        4.Java线程的创建:常用两种继承Thread、实现Runnable,不过,在调用时,都得使用Thread类实例的start方法。实现线程的方法,都在Run方法中写。

        5.线程的安全性:线程一旦遇到错误崩溃,大概率会使整个进程崩溃。

Java线程池机制:

        1.池化思想:在使用前为你创建好实例,在你使用后放回池内,不销毁。在使用时,节省了创建、销毁的步骤,节约时间。

        2.线程池的理解:如果你是A银行行长,A银行有10个柜台,为了保持工作通畅、效率高、并尽量节约人力资源,你会怎么做?

                假设,如果每天5个人轻松应对,

                1.行为(线程池初始化):就安排5个服务员,应对这些客户即可。

                问题1st:如果有更多的客人来了,怎么办?

                2.行为(增加线程数):很简单,多出来几个,我安排几个柜台,比如6个人来了,那我再开一个柜台。【切记,开一个柜台,就得打电话叫服务员从家过来,消耗时间很多】

                问题2nd:不仅有1st问题,客户的数目也不是固定的,可能10点来了6个,11点就只有3个。

                行为2的弊端:开柜台的效率太低了,等到服务员从家过来,前5个柜台说不定已经有空余柜台了,不可取。

                3.行为(等待队列):干脆提供一个休息区(等待队列),所有多出来的客户,先进去等待一下。

                问题3rd:问题好像解决了,不过如果100个客户过来,95个人在休息区等待,明显也不行啊?

                4.行为:所以,需要平衡休息区,这个要看情况,如果服务员处理速度很快,那休息区大点没关系,如果比较慢,休息区就小一点。【因为休息区也占用资源】

                问题4th:照样是100个客户过来,5个柜台实在应付不过来。

                5.行为(增加线程数):干脆把另外5个柜台也开了,从家过来慢点就慢点,总好过一直让客户等着。

                问题5th:200个客户过来了,队伍已经排到银行外面了,你想着,如果要办理这些业务,起码要做到明天。

                6.行为(拒绝策略):要不增加人手(明显柜台数固定)、要不叫客户去别的地方办理、要不干脆让他们回家明天再来【当然,Java提供第4种机制,把最先进入等待区的客户赶出去,让新客户进来,我实在不能理解】

                当然,如果处理完一波大的客流(比如中午总是有100个人来,其他时间就2、3个),我们也得学会利用人力资源,在中午时多开几个柜台,之后关闭几个柜台。【超时策略】

        3.线程池7个参数:就此,我们把Java线程池的6个参数都覆盖了,另外一个是构造线程池方式。【核心线程数、最大线程数、超时时间、超时时间单位、等待队列、线程池构造工厂、拒绝策略】

        4.Java线程池的相关类,都放在java.util.concurrent包下,使用举例:

public static void main(String[] args) {
        ExecutorService executor = new ThreadPoolExecutor(3, 5,
             1, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory());

        for(int i=0; i<100; i++){
            executor.execute(new Thread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    System.out.println(Thread.currentThread().getName()+"->正在执行!");
                }
            }));
        }

        executor.shutdown();
    }

以上内容即我想分享的关于线程、进程、Java线程池的一些知识。

        我是蚊子码农,如有补充,欢迎在评论区留言。个人也是初学者,知识体系可能没有那么完善,希望各位多多指正,谢谢大家。

  • 16
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值