程序员自我修养之Java篇

一、lock、synchronized 和 volatile的区别

        synchronzied 同步代码块底层原理 :  monitorenter指向同步代码块的开始位置,monitorexit指向同步代码块的结束位置。线程执行到monitorenter指令时,该线程对象持有锁,即线程获得monitor持有权,count计数器+1,获得线程锁,线程执行完毕后,执行monitorexit执行指令,count为0,释放锁。   注意:无论是正常结束还是异常结束,都会执行monitorexit指令

        synchronized 的同步方法的底层原理 :  ACC_SYNCHRONIZED的flag标记该方法是否是同步方法,从而执行相应的同步调用    

        synchronized 和 volatile 的区别

  volatile只能在线程内存和主内存之间存一个变量值,synchronized可以修饰类、对象、方法等,但是synchronized很消耗内存

        volatile的理解:具有可见性、有序性,不具备原子性、禁止指令重排。 volatile修饰的变量会强制把数值写入主内存中

        synchronized 和 lock 的区别

  synchronized是Java的关键字,Lock是接口

  synchronized是自动释放锁,Lock需要手动释放锁,所以写到try catch中并且在finally中释放锁

  synchronized无法中断等待的锁,Lock可以中断,它可以在激烈的读写操作

        synchromized比Lock性能好

        Java内存模型:原子性、可见性、指令重排序

        Java内存结构:堆、栈、方法区、常量区、静态区、程序计数器

二、volatile的原理讲解

数据原子操作指令

     原理:从工作线程内存到主内通过以上数据原子操作指令来完成,它会在底层汇编前面加上lock这样关键字

    lock关键字作用:

    可以直接让处理器缓存区的数据直接写回到主内里面

    也提供内存屏障,防止指令重排序

三、创建线程的方法

        1.继承thread方法

            Thread start 和 run 的方法

             start : 开启每一个线程的启动方法,一个线程只能开启一次,再开启就会报线程异常

             run  :  只是执行方法,可以多次执行,不能起到多线程作用

        2.实现Runnable接口

        3.实现CallBack接口    

        4.创建线程池

        5.使用定时器

四、sleep和wait(notify)区别

        sleep是Thread的内部的一个静态方法,可以再任何地方调用;wait是Object成员方法,只能在synchroized代码中被调用,其他地方调用会非法监控异常

  在等待时候,wait是释放锁的,用于线程交互;sleep会一直持有锁,不会改变锁的状态,用于线程切换cpu的状态

 五、线程池的使用    

        五种线程池、四种拒绝策略、三种阻塞队列

  五种线程池 

     threadPool = Executors.newCachedThreadPool();     //有缓冲的线程池,线程数 JVM 控制

        threadPool = Executors.newFixedThreadPool(3);      //固定大小的线程池,支持线程池并发

        threadPool = Executors.newScheduledThreadPool(2);  //固定大小的线程池,支持定时或者周期执行任务

        threadPool = Executors.newSingleThreadExecutor();   //单线程的线程池,只有一个线程在工作

        threadPool = new ThreadPoolExecutor();      //默认线程池,可控制参数比较多

        四种拒绝策略

  rejected = new ThreadPoolExecutor.AbortPolicy();           //默认,队列满了丢任务抛出异常

        rejected = new ThreadPoolExecutor.DiscardPolicy();          //队列满了丢任务不异常

        rejected = new ThreadPoolExecutor.DiscardOldestPolicy();   //将最早进入队列的任务删,之后再尝试加入队列

        rejected = new ThreadPoolExecutor.CallerRunsPolicy();       //如果添加到线程池失败,那么主线程会自己去执行该任务

        三种阻塞队列

  有限队列

        ArrayBlockingQueue<>(5);                             //基于数组的先进先出队列,有界

        无限队列

        SynchronousQueue<>();                                //无缓冲的等待队列,无界适用于       newCachedThreadPool线程池

  LinkedBlockingQueue<>();                            //基于链表的先进先出队列,无界适用于newFixedThreadPool、newScheduledThreadPool

        默认线程池的参数讲解:

  * corePoolSize:核心线程池大小

  * maximumPoolSize:最多线程池大小

        * keepAliveTime:表示空闲线程的存活时间

    * unit:keepAliveTime时间单位

    * workQueue:阻塞任务队列

    * threadFactory:新建线程工厂

   * RejectedExecutionHandler:保护策略

    线程池的submit和execute执行方法的区别

    1、submit在执行过程中与execute不一样,不会抛出异常而是把异常保存在成员变量中,execute直接抛出异常之后线程就死掉了,submit保存异常线程没有死掉

    2.submit有返回值,execute没有返回值


六、锁的概念

重入锁:当前已经拿到类的锁,实际上还是可以再调用有锁的方法

自旋锁: 当前拿到线程锁以后,其他线程不会就如休眠状态

互斥锁:当前线程拿到锁以后,其他线程就会进入休眠状态

读写锁的解释和场景

      当某线程拿到读锁的时候,只有具有读锁的线程可以申请读锁,但不能申请写锁    

      当某线程拿到写锁的时候,只有具有写锁的线程可以申请写锁,但不能申请读锁

      拿到申请读锁时候,不一定要读数据,但是申请写锁时候,一定要写数据,适用场景是只有读写锁,且读锁的需求比写锁的需求多

原子类:Atomic基本数据类型。 AtomicIntege(整数加锁)、AtomicBoolean(boolean加锁).......

AQS : ReetracntLock 就是用这个方法去写的

CountDownLatch : 通过wait进行等待,当减为0才会唤醒线程


七、HashTable、HashMap、ConcurrentHashMap、LinkHashMap之间的区别

ConcurrentHashMap的视频

https://www.bilibili.com/video/BV1BC4y187Ti    

    LinkHashMap和HashMap的区别

    LinkHashMap : 是HashMap的一个子类,它存储是有序的,HashMap : 它的存储是无序的。

    HashMap和HashTable是底层数组+链表实现

    ConcurrentHashMap是由Segment (ReentrantLock可重入锁)数组结构+HashEntry数组结构组成。

    HashTable和HashMap的区别:

    HashTable无论key还是value都不能为null,线程安全; HashMap可以存储null键和null值,线程不安全

    HashMap的扩容是:默认是16,扩容是2*old ,负载因子是0.75; HashTable的扩容是:默认是11,扩容是2*old+1

        HashMap的存值    

        ConCurrentHashMap的存值

        https://www.bilibili.com/video/BV1BC4y187Ti?p=18  视频观看

        ConcurrentHashMap是HashTable优化版,Hashtable中采用的锁机制是一次锁住整个hash表,从而在同一时刻只能由一个线程对其进行操作;而ConcurrentHashMap只是锁住当前线程的数据,其他线程还是可以访问该hash表

Android 中的SparseArray和HashMap的区别

优势:SparseArray比HashMap更省内存,在某些条件下性能更好,主要是因为它避免了对key的自动装箱(int转为Integer类型),它内部则是通过两个数组来进行数据存储的,一个存储key,另外一个存储value

SparseArray应用场景:

虽说SparseArray性能比较好,但是由于其添加、查找、删除数据都需要先进行一次二分查找,所以在数据量大的情况下性能并不明显,将降低至少50%。

满足下面两个条件我们可以使用SparseArray代替HashMap:

数据量不大,最好在千级以内

key必须为int类型,这中情况下的HashMap可以用SparseArray代替:


十三、JVM虚拟机理解

        对JVM理解的网址 : https://blog.jamesdbloom.com/JVMInternals.html 

      java的内存模型:原子性、可见行、指令重排序    

      visualGC(JDK里面自带)插件可以检查JVM的内存模型        

      1.JVM的内存结构

            堆区(新生代(1/3)、老生代(2/3))、栈区、方法区、静态区、程序计数器            

    2.JVM内存分配,新生代的大小可以在AndroidStudio上配置大小

            a.大的对象直接分配到老生代

            b.先分配到新生代,第一次GC之后会被放在survivor区,多次GC仍存活就会被放到老生代区

            c.第一次再往survivor区移动的对象时候,总对象超过它内存的百分之50就会被送到老生代区

            d.在GC先对老生代进行判断,是否所有的新生代对象的大小比老生代大,如果大就行一次Full GC的操作

        Minor GC  指的是发生在年轻代或者说新生代(Young space)中的gc

        Major GC 指的是发生在老年代(Tenured space)中的gc

        survivor区的作用是解决了碎片化,不用所有的回收对象都会被放在老生代里面,以防老生代很快填满

    3.如何判定对象是垃圾对象   

           a.引用技术法:有对象引用计数就+1,如果为0就会被回收掉。

           缺点是:一旦两个对象变量相会引用,对象销毁,但是还是无法被回收,计数不为0 

            b.可达性分析法

            c.如何判断一个类是否为无用类

                堆中不存在该类的任何实例

                该类的加载器ClassLoader已经被回收了

    4.垃圾回收算法

            a.回收策略

                标记-清除法 : 把标记的垃圾对象直接清除

                缺点:会有很多内存碎片,导致于无法连续使用

          标记-整理法 :一边将垃圾对象回收、一遍把存活对象向一端移动,保持内存连续完整性                

                复制算法 : 将内存一分为二,把可用对象复制到另外一半上,其余一次性清除

                缺点:浪费内存的使用

                分代收集法  : 这个是JVM主流算法,新生代回收新生代、老生代回收老生代

            b.垃圾回收器:它是把回收算法用代码实现,收集器都是可以在AndroidStudio上配置

              Serial收集器 : 它是一个单线程的收集器,它在进行垃圾回收,其他线程需要停止工作

                 ParNew收集器 :是Sercial多核版本的使用,作为新生代使用       

              Parallel Scavenge垃圾收集器 :适用于内存大于2G和2个CPU设备

   CMS垃圾收集器:采用标记-清除算法,只在老年代上使用

         优点:并发收集、并发处理、低停顿

         缺点:和用户线程抢占资源、采用标记-清除算法会处理对象较耗时且产生不连续的碎片内存、回收的不确定性会产生FullGC

       G1垃圾回收器 :采用复制算法  并发标记-->最终标记-->筛选回收

        筛选回收机制:先对各个内存大小进行排序,再符合GC停顿时间内,把这些垃圾分段回收

        G1垃圾回收器的种类:Minor GC、Major GC、Full  GC

九、触发GC的条件

   1.当应用程序空闲时,即没有应用线程再运行时,GC会被调用的

   2.JAVA内存不足的时候,GC会被调用

十、减少GC的开销措施

   1.不要显示调用System.gc()

   2.尽量减少创建临时对象(相当于减少垃圾的产生,从而延长第二次GC的触发时间),对象不用时候最好显示设置为null(有利于GC收集器判定垃圾,从而提高垃圾回收)

   3.尽量使用StringBuffer,而不用String来增加字符串

   4.能使用基本变量就不用封装好的对象(比如int ---> Integer对象)

   5.尽量减少使用静态变量(静态变量属于全变量,不会被GC回收掉,他们也会一直占用内存,增加GC的次数)


十三、Java的设计六原则

          单一原则、开闭原则、里氏替换、依赖倒置、接口抽离、迪米特法则  

十四、设计模式   

        装饰者和适配器模式的区别

        1.装饰者模式:给对象添加功能,可以动态生成和者取消    案例:FilterInputStream既包含InputStream和BufferInputStream两种流

        2.适配器模式:将一个接口转变成另一个接口,通过改变接口来达到重复使用的目的

案例:InputStreamReader是有Reader接口和InputStream接口组成一个新的接口

        外观模式和代理模式的区别

        3.外观模式:把复杂的方法合并成一个外观方法供外面使用,提供调用简单,侧重于方法

        4.代理模式:把一个功能封装在一个对象里面,然后供外界使用,侧重于是对象

        建造者模式和工厂模式的区别

        5.建造者模式:适用于复杂参数初始化,可以通过建造者模式来构建,侧重于方法

        6.工厂模式:创建复杂且大量的对象来构建,侧重于对象

        单例模式和共享元模式的区别

        7.单例模式:它是针对于有且只有一个对象,侧重于对象

        8.共享元模式:它是针对于一个共享数据来做处理,侧重于整体数据。例Handler的MessageQueue存储Message

        9.责任链模式

        发布订阅模式和观察者模式区别

        10.观察者模式 : 数据源直接通知订阅者发生改变  ,他比较关注一个关心数据源

        11.发布订阅模式 :数据源告诉第三方(事件频道)发生了改变,第三方再通知订阅者发生了改变,他比较关注事件消息

        12.桥接模式

        13.组合模式

        14.策略模式

十五、范型的上下通配符

    ? ----- > 通配符  :  java里面支持类的继承,而泛型不支持类的继承,? 代表所有类的父类

    extends---> 通配符上边界  : 只接受本身和自己的子类

    super---->通配下边界 : 只接受本身和自己的父类

    ? extends T  :  只支持本身和自己的子类的任何类型

    ? super T :  只支持本身和自己的父类的任何类型

    上边界和下边界什么时候使用:

    上边界:在读取T的数据,但是不写入时候

    下边界:在写入T的数据,但是不读取时候

    范型擦除:定义<T>这样的方法,编译器会把T认为是Object对象,再编译期间需要时候再强制转型

十六、内部类为什么可以调用外部类的成员变量

        在调用内部类的构造器初始化内部类对象的时候, 编译器默认也传入外部类的引用给内部类,这样就可以访问到外部类的成员和方法了,内部类也可以访问外部类的私有成员,最终通过编译器写成static形式来去访问     

十七、TCP和UDP的区别

        a.基于连接与无连接

        b.对系统资源的要求(TCP较多,UDP少)    

        c.UDP程序结构较简单  

        d.流模式与数据报模式    

        e.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。   UDP (应用场景 IP电话,实时视频会议)    

十八、三次握手和四次挥手的意义

        三次握手的目的是建立可靠的通信信道,主要的目的就是双方确认自己与对方的发送与接收机能正常


        四次挥手是表示自己发完了所有要发的数据,但还允许对方继续把没发完的数据发过来,确保数据都能完整发送

        TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

十九、GET请求和POST请求的区别

        1. 大小是否有限制:GET请求有限制;POST请求没有

        2.安全性:GET请求提交的数据都在URL中,可见,不安全;相对来说POST请求更加安全

        3.JS中获取参数上的区别:GET请求在JS中是通过Request.QueryString["xxx"]获取URL中的参数,而POST请求在JS中是通过Request.Form["xxx"]获取Form表单中的参数

十九、http1.0、1.1和2.0的区别

        http1.0和http1.1的主要区别如下:

        1、缓存处理:1.1添加更多的缓存控制策略(如:Entity tag,If-Match)

        2、网络连接的优化:1.1支持断点续传

        3、错误状态码的增多:1.1新增了24个错误状态响应码,丰富的错误码更加明确各个状态

        4、Host头处理:支持Host头域,不在以IP为请求方标志

        5、长连接:减少了建立和关闭连接的消耗和延迟。

        http1.1和http2.0的主要区别:

        1、新的传输格式:2.0使用二进制格式,1.0依然使用基于文本格式

        2、多路复用:连接共享,不同的request可以使用同一个连接传输(最后根据每个request上的id号组合成正常的请求)

        3、header压缩:由于1.X中header带有大量的信息,并且得重复传输,2.0使用encoder来减少需要传输的hearder大小

        4、服务端推送:同google的SPDUY(1.0的一种升级)一样

二十、JDK1.8的特性

        Lambda表达式

        函数式接口 -----> interface

        方法引用和构造器调用     :: 

        Stream API

        新时间日期API

        HashMap存储从头插入变为尾插入

https://space.bilibili.com/627881031?spm_id_from=333.788.b_765f7570696e666f.1

https://cs.android.com/android/platform/superproject;l=417 Android的原生文档

七、throw和throws的区别

   throw :  用在方法体内,跟的是对象名,throw抛出异常,一定会抛出某种异常

   throws :  用在方法后面,跟的是类名,它抛出的异常只是一种可能性,并不一定会抛出异常的

八、final、finalize、finally的关键字的区别

     final :  可以修饰类,修饰的类不能被继承 ; 可以修饰变量,该变量的数值就不能修改

   finally :  try ... catch 语句中使用

   finalize :  在垃圾回收时候使用,被清理对象没有被引用的情况下调用的。

九、Error和Exception的区别

            error和exception都是继承Throwable。

            Exception: 分为检查异常(CheckException)和非检查异常(RuntimeException),一般是代码代码错误引起,可以预料的意外情况,通过捕获并处理,以使程序重回正轨

            Error: 是Java运行时抛出的JVM层面的错误,不能捕捉,发生后只能安全的退出应用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容