zoukankan      html  css  js  c++  java
  • java多线程--线程和线程池

    线程池知识梳理

    linux操作系统进程和线程:(待完善)

    小企鹅镇楼

    先从最基本的概念慢慢往下看

    首先打开电脑电源后,cpu 执行bios(basic input output system,一段烧在计算机主板里的代码),此时没有内存,没有磁盘。

    bios做一些基本的硬件检测等操作,读取存储(光盘或者磁盘等)里一个扇区的代码(512字节)加载到内存的0x7c000位置,cpu然后从内存呢这个位置开始执行。

    这512个字节就是bootloader(常见的有grub,lilo等),bootloader 操作系统的代码引入进来,后续会cpu跳转保护模式,硬件初始化,硬件检查,文件系统初始化等等。

         这部分内容可以推荐一本  《自己动手写操作系统》,完全从零开始写操作系统,操作系强。

    由此可见,在电脑的硬件层没有进程或者线程的概念,bios导入代码,cpu从固定位置执行,被执行的代码继续引入代码和数据,cpu继续执行。

    如果这里动手写过代码,就会发现,基本都是汇编语言编写,所有的操作都是直接操作硬件,非常非常繁琐,无法完成大规模的工作,而且很多底层的操作完成是电脑硬件的操作

    难度大,容易出错且重复性非常高,所以先驱们把常用的操作写成一些汇编的方法供调用,慢慢就是操作系统的概念了 ,从Dos(DiskOperationSystem)到多线程操作系统Unix,linux,再到有图形的操作系统。

    再看Linux操作系统,linux操作系统教程一般包含 内存管理,进程管理和cpu调度资源分配,文件管理,网络等外部设备管理,内存是直接寻址cpu指令直接(load)获取数据,直接给cpu提供指令(方法端)给寄存器提供数据(数据段)。文件操作系统屏蔽了磁盘的基本操作,以文件的形式保存数据,方便读写,其他外部设备也是屏蔽了硬件细节,提供统一接口。

    我们接下来看下进程数据结构和调度方法,sched.h文件里 struct task_struct,进程是一个数据结构,标识进程的一些属性(名称,id,优先级,状态等),操作系统维护一个进程表,指向所有的进程,系统进程启动时创建并且运行。用户进程以其为父进程,创建后为Runnable 状态等待调度,调度后变运行状态直到运行结束或者主动(等待资源,sleep等)或者被动结束(时间片用完或者别其他高优先级进程抢占等)线程是轻量级的,可以一个进程创建多个线程,线程内部部分资源可以共享,进程比较重,线程比较轻。同一进程下的多个线程是可以在多核CPU下并行运行的。但2.4内核及以前的系统实现的线程没有内核支持,无法在多核的情况下并行运行。

    记得原来考虑过如果使用一个操作系统的进程实现多线程的效果,可以自己模拟操作系统的一整套多线程机制,自己编写一个进程对象,一个进程管理表。主流程扫描表,按照时间片或者其他方式轮流执行每个“进程” 的代码,执行完毕后保留现场,到下一次再被执行时初始化现场,新建进程时加入管理表,进程结束后删除记录。而且单cpu场景下,cpu本来只能同时做一个指令,宏观上是多线程,微观上其实还是单线程的。这里是凭印象写的,后续有时间再详细整理,linux系统博大精深这里只是抛砖引玉。

    linux 进程例子:

    Linux线程例子:

    Java的线程(待完善):

    java内部使用线程机制,可以运行一个java程序用jps看只增加一个进程(main函数执行时,进程名称为main), jstack  进程id ,看到所有线程。

    可以打开java的源码 java.lang.Thread ,java部分代码比较容易理解,但是涉及到的操作系统知识较多,后续再补充

    Java线程池:

    线程池接口 :  

    ExecutorService  接口,从接口看线程池提供的全部功能。

      ThreadPoolExecutor

      

      ForkJoinPool

      原理: 线程可回收利用,使用了blockingqueue(blockingqueue使用了 锁里的Condition)

    基本流程:  submit runnable 后 判断当前worker是否大于等于 coreSize,如果没有,新建worker,锁自己执行runnable,如果到了,放blockingqueue,blockingqueue满了,如果size小于max,新建worker。

                       worker执行完runnable,判断是否大于coresize,大于等待一段时间后销毁自己,否则取读blockingqueue的runnbale,读不到则被block

                            shutdown 方法 是 要获取worker锁, 这样在运行的worker会跑完,然后线程标识位置为 interupt

                            shutdownnow 直接置为interupt,不过置为interupt也不知直接线程就停止了,遇到判断标志位的才停止,例如wait和方法内部的判断等。

                                                                       

  • 相关阅读:
    2019/10/21 动手动脑
    2019/10/21 课堂测试---向数据库添加新用户
    2019/10/14 如何在静态方法中访问类的实例成员
    2019/10/14 构造函数、默认值、初始化块的优先级。
    2019/10/14 动手动脑---
    2019/9/30 极限测试(1)
    读《程序员的修炼之道------从小工到专家》有感 1
    课堂测试,统计小说<飘>前N个最常出现的单词
    Java课堂 动手动脑
    2019/9/23 课堂测试一 回文
  • 原文地址:https://www.cnblogs.com/thinkqin/p/11099392.html
Copyright © 2011-2022 走看看