1.1 Java基础

▼魔方 西西 提交于 2020-01-15 07:27:49

目录

1.1.1 Java程序运行原理分析

1.1.2线程状态

1.1.3线程中止

1.1.4内存屏障和CPU缓存

1.1.5线程通信

1.1.6线程封闭

1.1.7线程池


1.1.1 Java程序运行原理分析

1、class文件内容
    魔数:0xCAFEBABE
    版本:JDK版本
    访问标志:类的访问修饰符(public)
    常量池
    当前类
    超级类
    接口
    字段
    方法
    属性
2、JVM运行时数据区
    方法区:类信息、常量、静态变量、编译后的代码
    堆内存:创建的对象、OutOfMemoryError
    虚拟机栈:多个线程
              一个线程一个私有空间
              一个线程执行多个方法
              一个方法对应多个栈帧
              栈内存默认最大是1M
              为JAVA代码准备的
    本地方法栈:与虚拟机栈功能类似
                为Native方法准备的
    程序计数器:当前线程字节码指令执行位置    
    
栈帧:局部变量表、操作数栈、动态链接、方法返回地址、附加信息
线程共享主内存):方法区、堆内存
线程独占工作区):虚拟机栈、本地方法栈、程序计数器

1.1.2线程状态

线程的6个状态
    New:尚未启动的状态(没有调用start方法)
    Runnable:CPU正在执行、可运行(等待CPU调动)
    Blocked:线程阻塞等待锁(synchronized)
    Waiting:等待(没有等待时间,比如wait/join)
    Timed Waiting:具有指定等待时间的等待状态(比如sleep)
    Terminated:终止线程(正常执行完/异常终止)

1.1.3线程中止

正确的线程中止方法:interrupt标志位(控制循环的条件)
interrupt正常中止的情况:
    线程在调用Object类的wait()、wait(long)、wait(long,int),
                      Thread类的join()、join(long,int)、sleep(long,int)方法时被阻塞,interrupt会生效,抛出InterruptedException异常
    线程是被I/ONIO中的Channel所阻塞,interrupt会生效(抛出对应的I/O或NIO异常)

1.1.4内存屏障和CPU缓存

1、CPU性能优化手段:
    缓存(CPU的一级缓存的容量通常在32~4096KB)
        CPU读数据时,先在L1(一级缓存)中寻找,再从L2寻找,再从L3寻找,然后是内存,再后是外存储器
        CPU对缓存进行改动时,需要发通知给其他CPU
        CPU在读写缓存时,要监听其他CPU发出的通知,保证缓存的一致性
    运行时指令重排
        仅在单CPU自己执行时,能保证结果正确
        遵守as-if-serial语义(为提高并行度,不会对存在数据依赖关系的操作做重排序)
2、内存屏障
    写内存屏障(强制写入主内存):在指令后插入Store Barrier,让写入缓存中的最新数据更新写入主内存
    读内存屏障(强制读取主内存):在指令前插入Load Barrier,让高速缓存中的数据失效,强制重新从主内存加载数据

1.1.5线程通信

1、线程通信的2种机制
    wait/notify机制(有顺序要求、等待时会释放锁
        wait:当前线程等待,加入该对象的等待集合中,并且放弃当前持有的对象锁
        notify/notifyAll:方法唤醒一个或所有正在等待这个对象锁的线程
    park/unpark机制(没有顺序要求、等待时不会释放锁)
        park:等待(许可/令牌)
        unpark:提供(许可/令牌)

在lambda表达式中,this就是调用当前方法的对象,lambda不会创建对象
2、两种机制的优缺点
    wait/notify要求在同步关键字里使用(否则会抛出IllegalMonitorStateException(非法监视器状态异常)),免去死锁,但是一定要先调用wait,再调用notify,否则永久等待
    park/unpark没有顺序要求,但是park不会释放锁,所以在同步代码中使用要注意
3、伪唤醒
    指线程并不是因为notify、notifyAll、unpark等api调用而唤醒,是更底层原因导致的
    wait方法正确的判断方式
    synchronized(obj){
        while(<条件判断>)
            obj.wait();
        ...//执行后续操作
    }
    park方法正确的判断方式
    while(<条件判断>)
        LockSupport.park();
    ...//执行后续操作

1.1.6线程封闭

线程封闭:将数据封闭在线程中而避免使用同步的技术叫线程封闭
线程封闭具体体现ThreadLocal、局部变量
    ThreadLocal:每个线程都拥有自己独立的变量(副本)
    局部变量(栈封闭):位于执行线程的中,其他线程无法访问这个栈

1.1.7线程池

代码参考Demo9

1、线程:java中是一个对象
          操作系统的资源
          创建、销毁需要时间
2、线程池:为了方便控制线程数量
3、线程池原理
             线程池管理器:用于创建并管理线程池(创建线程池、销毁线程池、添加新任务)
             工作线程:线程池中线程(可循环执行任务)
              任务接口(Runnable):规定了任务的入口、任务执行完后的收尾工作、任务的执行状态
              任务队列:存放没有处理的任务(缓存机制)
4、线程池接口
             Executor:最上层的接口,定义了执行任务的方法execute
             ExecutorService:继承了Executor,扩展了Callable、Future、关闭方法
             ScheduledExecutorService:继承了ExecutorService,增加了定时任务相关的方法
5、线程池实现类
             ThreadPoolExecutor:基础、标准的线程池实现
             ScheduledThreadPoolExecutor:继承了ThreadPoolExecutor,实现了ScheduledExecutor中相关的定时任务的方法
6、Executors工具类
             newFixedThreadPool(int nThreads):核心线程数=最大线程数,无界队列
             newCachedThreadPool():核心线程数=0,最大线程数=Integer.MAX_VALUE,无界队列

                   SynchronousQueue每次执行offer方法先判断有没有空闲线程,如果没有空闲线程offer方法失败,接着创建一个新的线程
             newSingleThreadExecutor():只有一个线程的线程池,无界队列
             newScheduledThreadPool(int corePoolSize):核心线程数由参数指定,最大线程数=Integer.MAX_VALUE,无界队列
7、任务execute过程
             线程池达到核心线程数量,就判断工作队列是否已满,如果已满,就判断是否达到最大线程数量,如果没达到,就建新线程执行任务

    
调用线程池的shutdown方法:不接收新的任务,等已在线程池的任务全部执行完后,再终止线程池
调用线程池的shutdownNow方法:立刻终止,不接收新的任务,返回等待任务数,线程池中未执行完的任务被终止(抛出interruptedException)
确定合适数量的线程
    计算型任务:cpu数量的1~2倍
    IO型任务:根据具体的IO阻塞时长进行考量(tomcat默认最大线程数200) 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!