前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java 面试杂记

java 面试杂记

作者头像
Tim在路上
发布2020-08-04 10:28:20
3700
发布2020-08-04 10:28:20
举报

git 和 svn 的区别

1.git 是分布式的,svn不是,每个开发人员从中心版本库/服务器上chect out代码后会在自己的机器上克隆一个自己的版本库。 2.git 把内容安装元数据进行存储,svn是按照文件进行存储

常见的sql问题考察

  1. 查询学生每一个科目的最高分
select class,max(score) from table group by class;
  1. 查询每个科目都大于80分的学生姓名

只要有一个小于80就加入集合

select distinct name from table where name not in (select name from table score <= 80);
  1. 查询每一个学生的最高的科目
select a.student,a.class from table a ,(select student ,max(score) as max_score from table group by student) b where a.score = b.max_score and a.student = b.student;
  1. 查询平均分大于80分的学生
select student from table group by student having avg(score) > 80;
  1. 查询有两个分数相同的学生
select student,score,count(1) group by student,score having count(score) > 2;
随机打乱数组

可以保证扫面点左边的数字都是尚未确定位置的,而右边的数字都是已经安排好位置的

    public static <T> void swap(T[] a, int i, int j){
        T temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

    public static <T> void shuffle(T[] arr) {
        int length = arr.length;
        for ( int i = length; i > 0; i-- ){
            int randInd = rand.nextInt(i);
            swap(arr, randInd, i - 1);
        }
    }
32位的计算机最多可以管理4G的内存

2 ^ 32 = 4G 2 ^ 64 = G 当然这是理论值

冯诺依曼内存模型

什么是守护进程?
  1. 守护进程(daemon)是生存期长的一种进程,没有控制终端,的后台运行的进程。
  2. 需要注意的是,用户层守护进程的父进程是 init进程(进程ID为1)
  3. 守护进程程序的名称通常以字母“d”结尾
什么是临界区?如何解决进程间的冲突
  1. 多个进程进入临界区一次只能进入一个
  2. 如果一个已经进入,其他都只能等待
  3. 进入临界区,必须在有限时间内退出,以便其他进程进入临界区
  4. 自己时间不能进去临界区,应该让出避免“忙等”
一个方法加了Synchronized ,其他线程能否进入此对象的其他方法;

1.如果其他方法没加synchronized 可以进去; 2.如果这个方法内部调用wait,其他synchronized方法也可以进去,没有调wait,不能进去其他synchronized方法; 3.如果其他方法是静态的他用的同步锁和当前不同可以进去;

如何保证线程的安全性

保证可见性和原子性

java 初始化顺序
  1. 父类静态变量静态块
  2. 子类的静态变量静态块
  3. 父类变量初始化块构造方法
  4. 子类变量初始化块构造方法
mysql 为什么默认隔离级别是可重复读?

这是因为,mysql 如果打开语句级binlog就不支持,读已提交和读未提交两个事物隔离级别;

mysql 设置默认隔离级别为可重复读的原因是:

  1. 读已提交,会有不可重复读的问题
  2. binlog 要求sql串行化;

其次,mysql的可重复读,在一定程度上也避免了幻读的问题;

InnoDB通过gap锁来避免幻象,从而实现SQL的可串行化,保证Binlog的一致性。

其实,RR隔离级别的防止幻象主要是针对写操作的,即只保证写操作的可串行化,因为只有写操作影响Binlog;而读操作是通过MVCC来保证一致性读。

mysql 查询慢的原因以及优化步骤
  1. 设置关闭缓存set_no_cache,看看是否真的慢;
  2. 每个字段单独查询,查看他们的区分度和查询的速度
  3. 通过explain查看执行计划是否一致
  4. order by limit 形式的sql语句让排序的表优先查
  5. 加索引时参照建索引的几大原则

原则有:

  1. 最左前缀匹配原则
  2. 尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*)
  3. 尽量的扩展索引,不要新建索引。
隔离级别RR下的死锁情况
TX1 TX2
begin;  
update b set name2='test' where id=2999; 对id:2999加LOCK_X锁   

update b set name2='test' where id=999;

使用insert select 查询 select 会加锁

begin;
insert into a select * from b where id in (996,997,998,999,2995,2996,2997,2998,2999);对id:在加锁到996,997,998,999,2995,2996加LOCK_S锁,在对id:2997加锁前睡眠30秒,为下面的update语句腾出时间) 
update b set name2='test' where id=999;对id:999加LOCK_X锁等待但发现已经加LOCK_S锁,需等待

描述:一个事务内要更新两个id的数据,id = 2999,id = 999; 另一个个事务在他执行了一个更新语句后,要执行包含id = 2999.id = 999 的插入,但是需要等待第一个事务释放锁,但是第一个事务的第二个语句,又需要第二个事务释放id = 999 的锁,最终形成死锁;

尽量少使用insert search

如何删除表的重复数据;

思路查找出最小的id,只保留最小的其他删除

delete from order where id not in (select id from ( select min(id) as id from order group by order_number) as b);


delete from table where id not in (select min(id) from table group by name having count(name)>1) and  id in (select id group by name having count(name)>1)
使用 mysql 做队列

开启两个事务来读取状态,会将所有未消费的进行锁住;

 update user set session=CONNECTION_ID(),status='using' where status='un_use' limit 2;
为什么重写 equals 要重新 hashcode;

保证hash时,相同的hash到同一个位置

String 和 StringBuilder 的区别

String 和 StringBuilder 是效率和内存分配结果 当我们通过+来拼接字符串时,编译器会自动替我们优化成StringBuilder来拼接

  1. 目前 String 和 StringBuilder 编译优化后一样
  2. String 在循环中操作会导致很多StringBuilder,反编译以后的代码,我们可以发现,原来字符串常量在拼接过程中,是将String转成了StringBuilder后,使用其append方法进行处理的。
 public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: ldc           #2                  // String
         2: astore_1
         3: iconst_0
         4: istore_2
         5: iload_2
         6: bipush        10
         8: if_icmpge     36
        11: new           #3                  // class java/lang/StringBuilder
        14: dup
        15: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        18: aload_1
        19: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        22: iload_2
        23: invokevirtual #6                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        26: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        29: astore_1
        30: iinc          2, 1
        33: goto          5
        36: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
        39: aload_1
        40: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        43: return
      LineNumberTable:
        line 10: 0
        line 11: 3
        line 12: 11
        line 11: 30
        line 14: 36
        line 15: 43
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            5      31     2     i   I
            0      44     0  args   [Ljava/lang/String;
            3      41     1   res   Ljava/lang/String;
      StackMapTable: number_of_entries = 2
        frame_type = 253 /* append */
          offset_delta = 5
          locals = [ class java/lang/String, int ]
        frame_type = 250 /* chop */
          offset_delta = 30
}
java 泛型实现的原理?

概念用法:

Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。

List<object>和List<String>

泛型擦除:

public void test(List<Integer> li)

public void test(List<String> Li)

编译出错

在程序中定义了一个ArrayList泛型类型实例化为Integer的对象,如果直接调用add方法,那么只能存储整形的数据。不过当我们利用反射调用add方法的时候,却可以存储字符串。这说明了Integer泛型实例在编译之后被擦除了,只保留了原始类型。

类型擦除引起的问题及解决方法?

  1. 先检查再编译,既然类型擦除了,如何保证我们只能使用泛型变量限定的类型呢?java是如何解决这个问题的呢?java编译器是通过先检查代码中泛型的类型,然后再进行类型擦除,在进行编译的。
  2. 在Java中,像下面形式的引用传递是不允许的:
ArrayList<String> arrayList1=new ArrayList<Object>();//编译错误
ArrayList<Object> arrayList1=new ArrayList<String>();//编译错误

3、类型擦除与多态的冲突和解决方法,我们本意重写setValue和getValue方法的子类,竟然有4个方法,其实不用惊奇,最后的两个方法,就是编译器自己生成的桥方法。可以看到桥方法的参数类型都是Object,也就是说,子类中真正覆盖父类两个方法的就是这两个我们看不到的桥方法。而打在我们自己定义的setvalue和getValue方法上面的@Oveerride只不过是假象。而桥方法的内部实现,就只是去调用我们自己重写的那两个方法。 所以,虚拟机巧妙的使用了巧方法,来解决了类型擦除和多态的冲突。

如何拷贝一个数组

System.arrayCopy()

线程池如何做到重用?

使用预分配先创建一定数量的核心,执行完会继续阻塞,等待新的任务,其他大于核心线程数的线程会在一定时间后进行回收;

jvm能否自己关闭线程池

如果程序中不再持有线程池的引用,并且线程池中没有线程时,线程池将会自动关闭。

线程池自动关闭的两个条件:1、线程池的引用不可达;2、线程池中没有线程; 这里对于条件2解释一下,线程池中没有线程是指线程池中的所有线程都已运行完自动消亡。

  1. 然而我们常用的FixedThreadPool的核心线程没有超时策略,所以并不会自动关闭。所以我们在使用fixedThrePool核心线程时需要适当调用Shutdown方法,防止内存溢出。
  2. 可以自动关闭的是CachedThreadPool 线程。CachedThreadPool的线程keepAliveTime 默认为 60s ,核心线程数量为 0 ,所以不会有核心线程存活阻止线程池自动关闭。
synchronize和lock锁如何选择

在并发度低情况下使用 Synchronized ,这是因为,Synchronied 有一个锁升级的过程;

在要求中断,多个等待队列,可操作性性的,并发度高的情况下使用Lock锁;

常见线程同步工具,什么场景下使用

Semaphore CountDownLatch CyclicBarrier Exchanger Phaser

Semaphore 信号量是一类经典的同步工具。信号量通常用来限制线程可以同时访问的(物理或逻辑)资源数量。

CountDownLatch 一种非常简单、但很常用的同步辅助类。其作用是在完成一组正在其他线程中执行的操作之前,允许一个或多个线程一直阻塞。

CyclicBarrier 一种可重置的多路同步点,在某些并发编程场景很有用。它允许一组线程互相等待,直到到达某个公共的屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier在释放等待线程后可以重用,所以称它为循环的barrier。

Phaser一种可重用的同步屏障,功能上类似于CyclicBarrier和CountDownLatch,但使用上更为灵活。非常适用于在多线程环境下同步协调分阶段计算任务(Fork/Join框架中的子任务之间需同步时,优先使用Phaser)

Exchanger允许两个线程在某个汇合点交换对象,在某些管道设计时比较有用。Exchanger提供了一个同步点,在这个同步点,一对线程可以交换数据。每个线程通过exchange()方法的入口提供数据给他的伙伴线程,并接收他的伙伴线程提供的数据并返回。当两个线程通过Exchanger交换了对象,这个交换对于两个线程来说都是安全的。Exchanger可以认为是 SynchronousQueue 的双向形式,在运用到遗传算法和管道设计的应用中比较有用。

线程池原理

预创建技术,创建流程

一写多读 voliate,多写多读 cas
多次调用start()

Java的线程是不允许启动两次的,第二次调用必然会抛出IllegalThreadStateException,这是一种运行时异常

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • git 和 svn 的区别
  • 常见的sql问题考察
    • 随机打乱数组
      • 32位的计算机最多可以管理4G的内存
        • 什么是守护进程?
          • 什么是临界区?如何解决进程间的冲突
            • 一个方法加了Synchronized ,其他线程能否进入此对象的其他方法;
              • 如何保证线程的安全性
                • java 初始化顺序
                  • mysql 为什么默认隔离级别是可重复读?
                    • mysql 查询慢的原因以及优化步骤
                      • 隔离级别RR下的死锁情况
                        • 如何删除表的重复数据;
                          • 使用 mysql 做队列
                            • 为什么重写 equals 要重新 hashcode;
                              • String 和 StringBuilder 的区别
                                • java 泛型实现的原理?
                                  • 如何拷贝一个数组
                                    • 线程池如何做到重用?
                                      • jvm能否自己关闭线程池
                                        • synchronize和lock锁如何选择
                                          • 常见线程同步工具,什么场景下使用
                                            • 线程池原理
                                              • 一写多读 voliate,多写多读 cas
                                                • 多次调用start()
                                                相关产品与服务
                                                云数据库 SQL Server
                                                腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
                                                领券
                                                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档