从面试到技术提升(Java篇-上卷)

背景

其实,这系列文章我构思了很久。从我大概2016年初断断续续在CSDN上写博客开始,我就想好好整理一篇Android的综合文章。奈何那个时候功力尚浅,没办法驾驭(虽然现在依然彩笔一支)。
时至今日,算是正式开始动笔,其实之前想过很多文章计划,比如2018年开年的周期计划。不过写了8篇便放弃了。今天借着正正经经写公众号(IT面试填坑小分队)的机会,把这个《地表有点强》系列坚持下去,加油!

OK,闲话不说。先从Java开始~


《Java篇-上卷》

1、new一个类会发生什么?

Model model= new Model ()

  • JVM会通过双亲委派机制将Model .class加载到内存中。
  • 执行类里的静态代码块(如果有的话)。
  • 在堆内存中申请内存空间,并分配内存地址给我们真正的Model对象。
  • 在堆/栈内存里建立对象的属性(基本类型在栈中,引用类型和数组在堆中),并进行初始化赋值。
  • 开始对象的构造代码块初始化(如果有的话)。
  • 调用对象对应的构造方法进行初始化。
  • 将对象的被分配的内存地址赋值给model变量。

概念性的描述:

  • 加载:首相将类的全部信息加载到JVM的方法区中,然后在堆区中实例化一个java.lang.Class对象,作为方法去中这个类的信息入口(可以理解成是这个java代码的数据结构)。
  • 连接:分为三个部分:
    • 验证:验证类是否合法(判断这个代码文件是否符合JVM的标准)。
    • 准备:为静态变量分配内存并设置赋初始值,非静态变量在此时不会被分配内存(还没出生,也就是为什么静态不能调用非静态)。
    • 解析:将常量池里的符号引用转换为直接引用。
  • 初始化:初始化类的静态赋值语句和静态代码块,主动引用(就是那几种可以造成类初始化的行为)会被触发类的初始化,被动引用不会触发类的初始化。
  • 使用:执行类的初始化,主动引用会被触发类的初始化,被动引用不会触发类的初始化。
  • 卸载:卸载过程就是清楚堆里类的信息,以下情况会被卸载:① 类的所有实例都已经被回收。② 类的ClassLoader被回收。③ 类的CLass对象没有被任何地方引用,无法在任何地方通过 反射访问该类。(GC)

2、双亲委派机制?

谈到双亲委派,必须要提到类加载器

类加载器可以分为三类:

启动类加载器(Bootstrap ClassLoader):负责加载<JAVA_HOME>\lib目录下或者被-Xbootclasspath参数所指定的路径的,并且是被虚拟机所识别的库到内存中。

扩展类加载器(Extension ClassLoader):负责加载<JAVA_HOME>\lib\ext目录下或者被java.ext.dirs系统变量所指定的路径的所有类库到内存中。

应用类加载器(Application ClassLoader):负责加载用户类路径上的指定类库,如果应用程序中没有实现自己的类加载器,一般就是这个类加载器去加载应用程序中的类库。

聊一下双亲委派模型,流程图如下所示


双亲委派

简单流程:如果一个类加载器收到了加载类的请求,它不会自己立即去加载类,它会先去请求父类加载器,每个层次的类加载器都是如此。层层传递,直到传递到最高层的类加载器,只有当 父类加载器反馈自己无法加载这个类,才会有当前子类加载器去加载该类。

落实到代码上就是:

public abstract class ClassLoader {
    
    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException  {
            //首先,检查该类是否已经被加载
            Class c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    //先调用父类加载器去加载
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {            
                }

                if (c == null) {
                    //如果父类加载器没有加载到该类,则自己去执行加载
                    long t1 = System.nanoTime();
                    c = findClass(name);
                }
            }
            return c;
    }
}

3、如何判断对象死了?

引用计数法:有对这个对象的引用就+1,不再引用就-1,但是这种方式看起来简单美好,但它却无法解决循环引用的问题。

可达性分析算法:可达性分析算法通过一系列称为GC Roots的对象作为起始点,从这些节点从上向下搜索,搜索走过的路径称为引用链,当一个对象没有任何引用链 与GC Roots连接时就说明此对象不可用,也就是对象不可达。(也就是说可以被回收)

什么样的对象才能被称之为GC Roots对象?

  • 虚拟机栈中引用的对象(栈帧中的本地变量表)
  • 方法去中类的静态属性引用的对象
  • 方法区中常量引用的对象
  • Native方法引用的对象

4、synchronized理解?

synchronized同步的俩种写法:

  • synchronized(this):对象锁
public synchronized void method(){}

public void method(){
  synchronized(this) {}
}
  • synchronized(ClassName.class):类锁
public void method() {
   synchronized(ClassName.class) {}
}

public static synchronized method(){}

它们的区别大概可以这么理解:
对象锁:Java的所有对象都含有1个互斥锁,这个锁由JVM自动获取和释放。线程进入synchronized方法的时候获取该对象的锁(也就是传入的对象),当然如果已经有线程获取了这个对象的锁,那么当前线程会等待;synchronized方法正常返回或者抛异常而终止,JVM会自动释放对象锁。

类锁:首先来说,Java类可能会有很多个对象,但是只有一个Class对象,也就是说类的不同实例之间共享这一个的Class对象。Class对象就是一个特殊的Java对象。 类锁和对象锁不是同一个东西,一个是类的Class对象的锁,一个是类的实例的锁。也就是说:一个线程访问静态synchronized的时候,允许另一个线程访 问对象的实例synchronized方法。反过来也是成立的,因为他们需要的锁是不同的。


5、如何理解volatile?

首先我们先了解一下JMM,Java内存模型。

Java内存模型规定了所有变量(这些变量包括实例变量、静态变量等,但不包括局部变量、方法参数等,因为这些变量存放在栈中,是线程私有的,并不存在竞争)都存在主内存中,每个线程会有自己的工作内存,工作内存里保存了线程所使用到的变量在主内存里的副本拷贝,线程对变量的操作只能在自己的工作内存里进行,不能直接读写主内存,彼此线程之间也不可见。

Java线程模型

volatile有两条关键的语义:

  • 保证被volatile修饰的变量对所有线程都是可见的
  • 禁止进行指令重排序

非原子性操作除外,也就是说i++这种操作,用volatile修饰是没办法保证同步的,需要用到AtomicInteger

为什么自增不行?
因为i++操作,是多个步骤:首先取出i的值,因为有volatile的修饰,这时候的值是没有问题的。
但是自增的时候,别的线程可能已经把i修改了比如+1,这种情况下就此线程如果写入成功就把i的值改错误了。


6、单例

经典的单例写法:(但是此方式没办法应对反射破坏)

public class Singleton {

    //volatile保证了:1 instance在多线程并发的可见性 2 禁止instance在操作是的指令重排序
    private volatile static Singleton instance;

    private Singleton(){}

    public static Singleton getInstance() {
        //第一次判空,保证不必要的同步
        if (instance == null) {
            //synchronized对Singleton加全局所,保证每次只要一个线程创建实例
            synchronized (Singleton.class) {
                //第二次判空时为了在null的情况下创建实例
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

枚举的单例方式可以避免反射破坏,目前正在学习其中的原理,不要zhaoji...


7、手写一下生产者和消费者模型


public class Main {
    private static Integer count = 0;
    private static final Integer FULL = 10;
    private static Object LOCK =new Object;
    
    public static void main(String[] args) {
        Main main = new Main();
        new Thread(main .new Producer()).start();
        new Thread(main .new Consumer()).start();
        new Thread(main .new Producer()).start();
        new Thread(main .new Consumer()).start();
        new Thread(main .new Producer()).start();
        new Thread(main .new Consumer()).start();
        new Thread(main .new Producer()).start();
        new Thread(main .new Consumer()).start();
    }
    class Producer implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                synchronized (LOCK) {
                    while (count == FULL) {
                        try {
                            LOCK.wait();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    count++;
                    Log.d("test",Thread.currentThread().getName() + "生产者生产成功,目前总共有" + count);
                    LOCK.notifyAll();
                }
            }
        }
    }
    class Consumer implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (LOCK) {
                    while (count == 0) {
                        try {
                            LOCK.wait();
                        } catch (Exception e) {
                        }
                    }
                    count--;
                   Log.d("test",Thread.currentThread().getName() + "消费者消费成功,目前总共有" + count);
                    LOCK.notifyAll();
                }
            }
        }
    }
}


呃...

写完突然发现,有点随意了。这些内容好像完全不相干。不管了,大家就当琐碎的知识点,学习吧当然如果文中有错误的地方,欢迎评论区之出。因为这毕竟也只是我自己的学习总结~

推荐一个立志减少IT面试踩坑的公众号

因为身边的同学从事互联网相关职业的比较多,并且大家闲时聊天时总会吐槽找工作有很多坑,所以打算把身边同学找工作的经验,统统收集起来。提供给想从事这方面同学,希望圈内好友可以共同进步,共同少踩坑。

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

推荐阅读更多精彩内容