• 复习笔记


    一、Java基础

    1. JVM内存模型
      三部分:类加载器子系统运行时数据区执行引擎
      类加载器:启动类加载器 扩展类加载器 应用程序类加载器 自定义类加载器;双亲委派模式,加载请求最终委派到启动类加载器,父类加载器无法完成加载,子类加载器才会进行加载,保证安全性,避免重复加载
      内存模型:

      方法区:存放类的信息(字段信息、方法信息、静态变量、ClassLoader引用、Class引用等),常量池也在方法区
      :存放对象实例和数组值。堆和方法区被所有线程共享,所以在进行实例化等操作时,要解决同步问题
      Java栈:有栈帧组成,一个栈帧对应一个方法调用;栈帧又是有局部变量区和操作数栈两部分组成;java栈主要用于存储:方法参数、局部变量、中间运算结果;线程私有,无序考虑栈同步访问问题
      本地方法栈:保存native方法进入区域的地址
      PC寄存器:存放下一条要执行的指令在方法内的偏移量

      执行引擎:JVM执行Java字节码的核心,执行方式:解释执行、编译执行、自适应优化执行等

    2. JVM垃圾回收
      Java的所有释放都由 GC 来做,GC除了做回收内存之外,另外一个重要的工作就是内存的压缩,增加了安全性,当然也有弊端,比如性能这个大问题
      根据生命周期,把对象分为:年轻代、年老代、持久代(持久代在方法区中,负责保存反射对象)
      年轻代:刚实例化的对象,该区被填满时,GC会将对象移到Old区;会被频繁回收
      年老代:年轻代堆空间中长期存活的对象会转移到年老代堆空间中
      回收方式:年轻代的是 次收集(Minor GC);年老代的是 全收集(Full GC),System.gc()是全收集
      当年轻代堆空间满了的时候,会触发次收集将还存活的对象移到年老代堆空间。当年老代堆空间满了的时候,会触发一个覆盖全范围的对象堆的全收集

      不同的引用类型, GC会采用不同的方法进行回收https://www.cnblogs.com/yw-ah/p/5830458.html
      强引用:如A a = new A(),宁愿OutOfMemoryError也不会回收
      软引用:SoftReference<Object> sf = new SoftReference<Object>(obj);内存不够时回收
      弱引用:WeakReference<Object> wf = new WeakReference<Object>(obj);第二次垃圾回收时回收
      虚引用:PhantomReference<Object> pf = new PhantomReference<Object>(obj);垃圾回收时回收,主要用于检测对象是否已经从内存中删除

    3. java7开始,switch支持了String,所以现在switch支持 byte short int char String enum
    4. 方法重载:方法名一样、参数不一样、不能通过返回类型判断;在同一个类中
    5. 方法重写(覆盖):返回类型、方法名、参数都要一致;F f = new S(); f.m1()调用的是子类中的m1
    6. 隐藏:静态方法只能被继承、不能被覆盖,父类和子类中存在相同的静态方法,这时候发生的是隐藏,F f =new S();f.m2(),调用父类中的m2 ;S f = new S();f.m2()调用子类中的m2,也就是说不会发生动态绑定
    7. this 两个用途
      表示当前对象
      构造方法中调用另外一个构造方法、必须在第一行。调其他构造方法的目的是减少代码的重复
    8. super
      要的到子类对象就必须先生成父类对象,可以在子类的构造函数中用super(),指定父类的构造方法,必须在第一行
      表示父类对象
    9. static代码块在类被加载时执行、且只会执行一次,不能在静态代码块中使用this 

     二、多线程

    1. 为什么要有多线程
      CPU在等待I/O的时候,是空闲的,这时候可以让他去做一些其他事,就能够更好的使用CPU的资源
    2. 多线程并发
      在程序中,对共享变量的使用一般遵循一定的模式,即读取、修改和写入三步组成。这三步执行中可能线程执行切换,造成非原子操作。锁机制是把这三步变成一个原子操作
      在多线程并发编程中synchronized和Volatile都扮演着重要的角色,Volatile是轻量级的synchronized,它保证了共享变量的“可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值(线程访问变量是否是最新值)。它在某些情况下比synchronized的开销更小
      volatile:
      java的内存分为主存和工作内存,线程共享主存,但线程有各自的工作内存;线程访问主存中的共享变量时,会复制一个副本到工作内存,修改的也是副本,使用缓存,修改之后并不会马上刷新到主存中去,其他线程就不会看到共享变量修改后的值;通过volatile关键字修饰变量之后,不使用缓存,会立即刷新到主存,其他线程可以获取到最新值     volatile 并不会有锁的特性,volatile只能保证可见性,不能保证原子性

      volatile和synchronized区别:
      a.volatile关键字是线程同步的轻量实现,性能比synchronized好,volatile只能修饰变量,synchronized可以修饰方法和代码块
      b.volatile能保证可见性,不能保证原子性;synchronized可以保证原子性和可见性,会将公共内存和私有内存的数据做同步处理
      c.volatile不会阻塞线程、synchronized会阻塞线程
      d volatile解决的是变量在多个线程之间的可见性,synchronized解决的是多个线程之间访问资源的同步性
      如:i++  即i=i+1  不是原子操作(一条指令完成),首先要从内存中取出i  再计算i  再将i写入内存

      synchronized和volatile,以及wait、notify等方法抽象层次低,在程序开发中使用比较繁琐,易出错
      而多线程之间的交互来说,存在某些固定的模式,如生产者-消费者和读者-写者模式,把这些模式抽象成高层API,使用起来会非常方便
      java.util.concurrent包为多线程提供了高层的API,满足日常开发中的常见需求
      Lock接口 :
      ReentrantLock类
      ReadLock类
      WriteLock类
      Condition接口,Lock接口代替了synchronized,Condition接口替代了object的wait、nofity

      synchronized和Lock的差别
      Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放

    3. 线程池
      由于频繁的创建、销毁线程会降低系统的性能,因此使用线程池来管理线程,使得线程可以重复利用,执行完一个任务并不被销毁,可以继续执行其他任务
      核心类:ThreadPoolExecutor
      属性:coreThreadSize核心线程数、  maxinumThreadSize最大线程数、keepAliveTime线程池线程数大于核心线程数时,空闲线程的存活时间  workQueue阻塞队列用来存储等待执行的任务,handler拒绝处理任务时的策略。threadFactory线程工厂,主要用来创建线程。还有其他属性
      方法:execute()向线程池提交一个任务,交给线程池去处理;submit()也是提交任务,但是能返回任务执行的结果;shutdown()关闭线程池,不接受新任务,等待正在执行的线程完成;shutdownNow()关闭线程池,不接受新任务,终止正在执行的线程
      工作原理:
      一个任务到来之后,查看线程池中线程数目,如果小于核心线程数,就创建线程执行任务,如果大于核心线程数,就再看工作队列是否满,不满就把任务添加到工作队列,如果工作队列也满了,就查看池中线程数是否小于最大线程数,如果小于,就创建线程执行任务,如果已经等于了最大线程数,就执行拒绝策略


      

    1. 数组
      保存相同类型的数据,定义的时候要指定长度,而且是固定的,有length属性
    2. 集合
      长度可以动态增长
      List  有序、可重复;可通过下标和迭代器遍历
      ArrayList  底层数组实现,方法不同步,非线程安全,查询快,增删慢
      LinkedList  底层双向链表实现,方法不同步,非线程安全,查询慢,增删快
      Vector  底层数组实现,方法同步,线程安全

      Set  无序、不可重复;没下标,只能通过迭代器遍历;加入Set的Object类型的元素要实现equals和hashCode方法
      HashSet  底层基于哈希算法的哈希表实现,性能优于TreeSet,需要排序时用TreeSet;可以有一个null
      TreeSet  底层二叉树实现,自动排好序的,不允许null

      Map  是一个接口,并不继承Collection;键值;key不重复
      HashMap  继承自AbstractMap类;底层哈希算法的哈希表实现,内部维护单链表;对key要重写equals和hashCode方法,非线程安全;key value都可以为null
      LinkedHashMap  内部维护一个双向链表,有序,非线程安全
      HashTable  继承自Dictionary类;,线程安全,key value都不能为null

      如何选择
      需要有序存储:List
      保证唯一性:Set
      以键值存储:Map


    三、常用API

    1. Object
      toString() 返回对象的字符串表示
      equals()两个引用是否指向统一个对象,等价于==
      hashCode() 两个引用指向同一个对象,即equals()为true,哈希码值就相同;指向不同的对象,哈希码就不同
    2. String
      重写了equals()方法,用于比较内容是否相同,hashcode()也重写了,即使哈希码相同,也可能是不同对象
      StringBuffer线程安全
      StringBuilder非线程安全,但速度比前者快
      String常用方法:
      toCharArray()将字符串转换为字符数组

    3. 日期
      Date  获得日期
      SimpleDateFormat  指定格式   日期转为字符串:format(dat);字符串转为日期:parse(str)
      Calendar 单例,通过getInstance()获得; calendar.setTime(new Date());初始化;format(calendar.getTime())//格式化;calender.get(Calendar.YEAR)

  • 相关阅读:
    LeetCode 172:阶乘后的零
    Ubuntu12.04更新出现 The system is running in low-graphics mode解决方法
    不加参数的存储过程
    PCC-S-02201, Encountered the symbol "DB_USER_OPER_COUNT"
    该思考
    关于export环境变量生存期
    会话临时表 ORA-14452
    如何创建守护进程--及相关概念
    2014年10月末
    6个月
  • 原文地址:https://www.cnblogs.com/gucl/p/8326095.html
Copyright © 2020-2023  润新知