JAVA高级知识复习(多线程篇)

以下题目均来自JAVA微信公众号,答案均来自互联网外加自己总结
话不多说,以下就是干货。
面向java高级篇。
1、为什么说序列化不安全:
序列化则是将java对象转换成二进制字节码的过程,反序列化则是将二进制字节码转换成java对象。在RMI调用时,所有private字段的数据都以明文二进制的形式出现在网络的套接字上,所以不安全。另外反序列化会通过反射生成一个新的对象,所以会破坏单例模式。
2、并发与并行的区别:
并发:多个线程间隔的执行,如A-B-A-B
并行:多个线程同时执行,强调同时。
3、线程的实现、状态、优先级、线程调度:
线程的四种方法:继承Thread类、实现Runnable接口、通过Callable和FutureTask、通过线程池。
线程的状态:
初始状态:即得到一个线程对象,就进入初始状态。
就绪状态:获得所有资源,等待CPU的调度。
运行状态:处于CPU的调度状态。
等待状态:处于这种状态,必须被显示唤醒。
超时等待:一段时间后自动唤醒。
终止状态:此线程不会在单独执行。
线程的优先级:可以通过设置线程的优先级(0至10),优先级高的线程获得CPU的概率较大。
线程调度:指的是系统为线程分配CPU的过程。调度方法主要分为两种:协同式线程调度、抢占式线程调度。
协同式:线程切换由线程本身决定,线程执行完后主动通知系统切换到另一个线程。
抢占式:线程的调度由系统决定。
4、线程池原理:
线程池的存在就是缩短线程创建和销毁的时间。线程池一般包括以下几个部分:
1、线程池管理器:用于创建并管理线程。
2、工作线程:线程池中线程。
3、任务接口:每个任务必须实现的接口,供工作线程调度任务的执行。
4、任务队列:用于存放没有处理的任务,提供一种缓存机制。
线程池工作流程大致为:提交一个任务到线程池,首先判断线程池中核心线程是否都在执行任务,若不是,则加入。若是,则会创建一个非核心线程,若非核心线程也满了,则加入任务队列任务队列,若任务队列也满了,则拒绝执行。
主要参数:
corePoolSize:核心线程数
maximumPoolSize:最大线程数,核心线程+非核心线程
keepAliveTime:非核心线程,若闲置时间过长,就会被回收。
workQueue:任务队列
5、什么是死锁,死锁如何排查:
死锁:两个及两个以上的线程拥有对方所需要的资源,互相等待对方释放。
如何排查:利用jstack工具。
6、CAS是什么:
CAS一种乐观锁的实现,保证变量的原子性。CAS操作提供三个操作数,内存位置,预期新值,新值。若内存位置的数和预期新值一样,则修改新值得值。此操作中会存在ABA问题。即一个变量的值A修改成B再修改成A,CAS操作会默认为没有修改,解决这一问题则在变量前加上一版本号。每次修改版本号加一。
7、数据库乐观锁与悲观锁:
数据库中默认实现的是悲观锁,如行锁,表锁等,数据库中并未实现乐观锁,一般需要自己实现,如在每一条数据加上一个版本号,每次修改操作是,会查看版本号是否被修改。
8、谈谈JVM中的锁机制
JVM中的锁级别一般分为无锁、偏向锁、轻量级锁、重量级锁:
无锁:即没有对资源加锁,所有线程都能访问并加以修改,但同时只有一个线程能修改成功。无锁的特点是会不断循环的去修改一个值,若没有线程冲突就会修改成功,否则将一直循环知道修改成功。CAS操作即是无锁的应用。
偏向锁:资源不断的被同一个资源所访问,该线程就会获取该锁。原理为会在对象头的标记字段中存储该线程的id,在线程的进入和退出时会检测标记字段中的线程id。获取偏向锁的线程不会自动释放锁,只有锁竞争时才释放。
轻量级锁:由偏向锁升级而来,被另外的线程访问,偏向锁就会升级为轻量级锁,线程通过不断的自旋CPU获取锁。
重量级锁:由轻量级锁升级而来,除拥有锁线程之外的线程全部阻塞。
以上的各种操作均是为了避免线程阻塞。
9、synchronized是如何实现的:
synchronized是基于jvm底层实现的,每个对象被实例化时都会带着一个Monitor锁。每个线程都会带有一个monitor列表。每一个被锁住的对象都与一个monitor关联。monitor有一个字段Owner存放线程的唯一标识。(具体参考synchronized的实现原理与应用)
10、ThreadLocal是什么:
是线程的局部变量,是每一个线程单独持有的,其它线程不能访问。修饰变量时,为每一个使用该变量的线程都提供一个副本,各线程直接互不影响。
11、手写一个死锁的程序


public class ALock {
    public static void main(String[] args) {
        Object o1 = new Object();
        Object o2 = new Object();
        Thread t1 = new Thread(new A1(o1,o2));
        Thread t2 = new Thread(new A2(o1,o2));
        t1.start();
        t2.start();
    }
}
class A1 implements Runnable{
    Object o1,o2;
    A1(Object o1, Object o2){
        this.o1 = o1;
        this.o2 = o2;
    }
    @Override
    public void run() {
        synchronized (o1){
            try{
                Thread.sleep(20000);
            }catch(Exception e){

            }
            synchronized (o2){

            }
        }
    }
}
class A2 implements Runnable{
    Object o1,o2;
    A2(Object o1, Object o2){
        this.o1 = o1;
        this.o2 = o2;
    }
    @Override
    public void run() {
        synchronized (o2){
            try{
                Thread.sleep(20000);
            }catch(Exception e){

            }
            synchronized (o1){

            }
        }
    }
}


		

			

你可能感兴趣的:(程序员,面试,应届生,java开发)