滴滴二面总结

记录一下滴滴二面没有答上来的两个题目

问题一:线程池如何知道线程的状态

这个问题我不知道是不是应该答线程的五种状态

并发编程:java线程池的五个状态_芳的程序员的博客-CSDN博客_java 线程池状态

问题二:synchronize修饰静态方法和非静态方法的区别

修饰静态方法,锁是加在类上的,类的所有对象竞争一把锁;修饰非静态方法,锁加在单个对象上,不同对象间没有竞争关系。

​​​​​​synchronized修饰静态方法和非静态方法 - 简书

首先,在java中,类只能被加载一次,引用会有多个。

然后,静态方法是不属于引用的,是属于这个类的。

synchronized如果修饰方法,jvm实现上其实是把所有的代码块用synchronized包裹住了。

synchronized(this){

    //业务逻辑

}

如果是修饰静态方法,这个this就不是引用了,就是类了。

如果是修饰普通方法的话,这个this就是这个类的引用。
https://www.baidu.com/link?url=2eRXCZP6LaSNArmclltMoim4nPuz88fGnCP8zbdt3YE3BUC03xWi2qfOL2GR20F8sGOokX58_99iSlDylpZB9a&wd=&eqid=bfec08b00000ffdd0000000362b037d5

来做一个实验吧

public class Solutionaaa {

    public synchronized static void sayhello(){
        for(int i=0; i<100; i++) {
            System.out.println("hello...");
        }
    }

    public synchronized void sayhi(){
        for(int i=0; i<100; i++) {
            System.out.println(Thread.currentThread().getName() + " -> hi...");
        }
    }


    public static void main(String[] args) {
        Solutionaaa solutionaaa1 = new Solutionaaa();
        Solutionaaa solutionaaa2 = new Solutionaaa();
        new Thread(new Runnable() {
            @Override
            public void run() {
                solutionaaa1.sayhi();
            }
        }, "Thread1").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                solutionaaa2.sayhi();
            }
        }, "Thread2").start();
    }


}

滴滴二面总结_第1张图片

可以看到synchronized修饰非静态方法且使用不同实例执行该方法的时候是线程非安全的 

将代码修改一下,使用同一个实例执行该方法

public class Solutionaaa {

    public synchronized static void sayhello(){
        for(int i=0; i<100; i++) {
            System.out.println("hello...");
        }
    }

    public synchronized void sayhi(){
        for(int i=0; i<100; i++) {
            System.out.println(Thread.currentThread().getName() + " -> hi...");
        }
    }


    public static void main(String[] args) {
        Solutionaaa solutionaaa1 = new Solutionaaa();
        new Thread(new Runnable() {
            @Override
            public void run() {
                solutionaaa1.sayhi();
            }
        }, "Thread1").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                solutionaaa1.sayhi();
            }
        }, "Thread2").start();
    }


}

滴滴二面总结_第2张图片

 可以发现使用synchronized修饰非静态方法且使用同一个实例执行该方法的时候是线程安全的

我们再来看一下修饰静态方法的情况

public class Solutionaaa {

    public synchronized static void sayhello(){
        for(int i=0; i<5; i++) {
            System.out.println(Thread.currentThread().getName() + " -> hello...");
        }
    }

    public synchronized void sayhi(){
        for(int i=0; i<5; i++) {
            System.out.println(Thread.currentThread().getName() + " -> hi...");
        }
    }


    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                sayhello();
            }
        }, "Thread1").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                sayhello();
            }
        }, "Thread2").start();
    }


}

滴滴二面总结_第3张图片

我执行了很多次,结果都是有序的,所以synchronized修饰静态方法的时候是线程安全的 

那么我们小结一下

使用synchronized修饰静态方法时是线程安全的

使用synchronized修饰非静态方法且使用同一实例执行方法时是线程安全的

使用synchronized修饰非静态方法且使用不同实例执行方法时是线程不安全的

最后再说一下二面的时候算法题,一共是做了两道题。第一道是自己实现一下栈,写出入栈和出站的方法;第二道是二分查找,都不是很难。

你可能感兴趣的:(java学习笔记,java,jvm,开发语言)