java大厂面试题第三季(未完)

前言

这篇文章主要讲解java开发中常见的面试题
主要来源是
尚硅谷Java大厂面试题第3季,跳槽必刷题目+必扫技术盲点(周阳主讲)

看之前可了解我之前做过的一些文章进行补充
java基础知识之面试题

通过学习该视频,以及翻阅源码以及自已的理解
主要博文如下

1. java基础

该知识涉及jvm的内存加载
以下代码可能会涉及这部分知识

  1. java之native关键字详细解析
  2. java之intern()详细分析(全)

代码如下

class test{
    public static void main(String[] args) {
        String str1 = new StringBuilder("58").append("tongcheng").toString();
        System.out.println(str1);
        System.out.println(str1.intern());
        System.out.println(str1 == str1.intern());

        System.out.println();

        String str2 = new StringBuilder("ja").append("va").toString();
        System.out.println(str2);
        System.out.println(str2.intern());
        System.out.println(str2 == str2.intern());

    }
}

通过代码输出
该值为
在这里插入图片描述

该解释以上两个链接可参考
最主要的原理还需要通过翻阅源码

  • 因为java这个字符串在执行string-Builder.toString()之前就已经出现过了,字符串常量池中已经有了它的引用,不符合intern()方法首次遇到的原则。
  • 有一个初始化的Java字符串(JDK出娘胎自带的),在加载sun.misc.Version这个类的时候进入常量池

主要的代码执行步骤为
system输出的时候会默认调用initializeSystemClass() 之后去Version

package sun.misc;

//反编译后的代码
public class Version {
	private static final String launcher_name = "java";
	...
}

sun.misc.Version类会在JDK类库的初始化过程中被加载并初始化,而在初始化时它需要对静态常量字段根据指定的常量值(ConstantValue〉做默认初始化,此时被sun.misc.Version.launcher静态常量字段所引用的"java"字符串字面量就被intern到HotSpot VM的字符串常量池——StringTable里了。

1.1 力扣算法

此处只涉及力扣第一道算法
最主要是如何通过优化算法以及如何进行选择最优的算法
可看我之前的文章
【leetcode】数组-两数之和

涉及到的其他算法也可以参考我博客中的算法专栏
算法专栏

2. JUC

涉及这部分底层的知识可参考我之前的文章
JUC高并发编程从入门到精通(全)

关于这部分的线程进程的相关知识可查看我之前的文章

  1. 【操作系统】线程与进程的深入剖析(全)
  2. java之Thread类详细分析(全)
  3. java之Thread类实战模板(全)
  4. java中lambda表达式

2.1 可重入锁

  • 可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的的内层方法会自动获取锁(前提是锁对象得是同一个对象),不会因为之前已经获取过还没释放而阻塞。
  • Java中ReentrantLock和synchronized都是可重入锁,可重入锁的一个优点是可一定程度避免死锁

必须是同一个对象,而且一个线程中的多个流程可以获取同一把锁,持有这把同步锁可以再次进入,自己可以获取自己的内部锁

锁的机制有显式(lock,通过人为进行锁定或者解锁,也有ReentrantLock的可重入锁)、隐式(Synchronized)

可重入锁的验证:
(主要是验证了如果外层进入了,内层的锁也是可以直接进入,而且不用撤回锁)

同步代码块

public class ReentrantLockDemo2 {
    Object object = new Object();

    public void sychronizedMethod(){
       new Thread(()->{
           synchronized (object){
               System.out.println(Thread.currentThread().getName()+"\t"+"外层....");
               synchronized (object){
                   System.out.println(Thread.currentThread().getName()+"\t"+"中层....");
                   synchronized (object){
                       System.out.println(Thread.currentThread().getName()+"\t"+"内层....");
                   }
               }
           }
       },"Thread A").start();
    }

    public static void main(String[] args) {
        new ReentrantLockDemo2().sychronizedMethod();
    }
    
}

同步方法

public class ReentrantLockDemo2 {

    public static void main(String[] args) {
        new ReentrantLockDemo2().m1();
        
    }
    
    public synchronized void m1() {
    	System.out.println("===外");
    	m2();
    }
    
    public synchronized void m2() {
    	System.out.println("===中");
    	m3();
    }
    
    public synchronized void m3() {
    	System.out.println("===内");
    	
    }
}

通过以上代码可得知
在一个synchronized修饰的方法或者代码块内部,调用本类的其他synchronized修饰的方法或者代码块时,可以永远得到锁

深究其代码原理
每个锁对象拥有一个锁计数器和一个指向持有该锁的线程的指针

  • 当执行monitorenter时,如果目标锁对象的计数器为零,那么说明它没有被其他线程所持有,Java虚拟机会将该锁对象的持有线程设置为当前线程,并且将其计数器加1。
  • 在目标锁对象的计数器不为零的情况下,如果锁对象的持有线程是当前线程,那么Java虚拟机可以将其计数器加1,否则需要等待,直至持有线程释放该锁。
  • 当执行monitorexit时,Java虚拟机则需将锁对象的计数器减1。计数器为零代表锁已被释放。

显式锁(即Lock)也有ReentrantLock这样的可重入锁

public class ReentrantLockDemo{

	static Lock lock = new ReentrantLock();


    public static void main(String[] args) {
      new Thread(()->{
         lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "\t get Lock");
            setLock();
        } finally {
            lock.unlock();
        }
       },"Thread A").start();
     
    }

    new Thread(()->{
         lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "\t get Lock");
            setLock();
        } finally {
            lock.unlock();
        }
       },"Thread B").start();
     
    }
    
    }
}

通过上面的代码可得知
每个线程都要有入锁和出锁,不然在同一层面尚会出错

2.2 LockSupport

  • 线程等待唤醒机制
  • 创建锁和其他同步类的基本线程阻塞原语。park()和 unpark()的作用分别是阻塞线程和解除阻塞线程,比wait/notify,await/signal更强
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农研究僧

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值