三、多线程

  1. 并行和并发有什么区别
    并行是指多个事件同一时间发生,并发是指在同一时间间隔内多个事情一起发生
    并行是在多个实体上同时发生的事件,并发是在同一实体上发生的过个事件,并行是物理行为,并发是逻辑行为
    并行是在多个处理器上同时处理多个事件,并发是在同一处理器上处理多个事件

  2. 线程和进程的区别
    进程是系统分配资源的基本单位,而线程是任务执行和调度的基本单位,进程可以包含多个线程,线程只能属于一个进程;同一进程内的线程共享资源

  3. 守护线程是什么
    线程分为用户线程和守护线程,用户线程比较好理解,就是我们在程序编写时的线程,守护线程的创建与用户线程基本一致,只需在调用Thread的start()方法之前,设置一下setDaemon(true),则线程就变成了守护线程
    守护线程负责为用户线程服务,在所有用户线程结束之后,会随着jvm的退出而立即销毁,由于守护线程不能保证在jvm退出时执行是否完毕,所以一些对资源的操作,如数据的写入、文件的相关操作等,都不能在守护进行中来完成;典型的守护线程为GC,在所有的用户线程都结束之后,不再涉及垃圾回收的问题,GC随着jvm的退出给销毁

  4. 创建线程有哪几种方式
    继承Thread,调用start()方法
    实现runable接口,通过thread创建
    通过Future和callable来实现(与第四种混合用)
    使用线程池框架如Executor

  5. runnable和callable的区别
    runnable没有返回值,callable有返回值,也可抛出异常

  6. 线程有哪些状态
    新建、就绪、运行、阻塞、销毁,其他人整理的一副图,觉得很好,引用过来
    在这里插入图片描述
    新建状态:
    使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
    就绪状态:
    当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
    运行状态:
    如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
    阻塞状态:
    如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
    等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
    同步阻塞:线程在获取 synchronized同步锁失败(因为同步锁被其他线程占用)。
    其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
    死亡状态:
    一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

  7. sleep()和wait()有什么区别
    sleep是线程中的静态方法,wait是object种的方法
    sleep不释放锁资源,wait会释放对象锁
    sleep与wait都使线程处于阻塞状态,但阻塞类型不同,wait属于同步阻塞
    sleep可以在任何地方使用,wait只能在同步代码块中使用

  8. notify()和notifyAll()有什么区别
    每个对象都有两个池,锁(monitor)池和等待池
    锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。
    等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁,同时线程A就进入到了该对象的等待池中。如果另外的一个线程调用了相同对象的notifyAll()方法,那么处于该对象的等待池中的线程就会全部进入该对象的锁池中,准备争夺锁的拥有权。如果另外的一个线程调用了相同对象的notify()方法,那么仅仅有一个处于该对象的等待池中的线程(随机)会进入该对象的锁池.
    notify可能会导致死锁,而notifyAll则不会

  9. 线程的run()和start()有什么区别
    线程的run()是线程执行的方法,start()则是启动相应的线程

  10. 10.创建线程池有哪几种方式
    固定数量的线程池:
    在这里插入图片描述
    不定长的
    在这里插入图片描述
    定长的定时任务
    在这里插入图片描述
    单线程池
    在这里插入图片描述
    单线程池定时任务
    在这里插入图片描述
    任务窃取线程池
    在这里插入图片描述

  11. 线程池都有哪些状态
    在这里插入图片描述
    5种状态,RUNNING,SHUTDOWN,STOP,TIDYING,TERMINATED
    在这里插入图片描述

  12. 线程池中submit()和execute()方法有什么区别
    execute():只能执行 Runnable 类型的任务。
    submit():可以执行 Runnable 和 Callable 类型的任务。
    submit()能获取返回值(异步)以及处理Exception。execute()方法不行。

  13. 怎么保证多线程的安全运行
    线程的安全主要保证原子性、可见性、有序性
    原子性:JDK的Automic、synchronized、Lock等保证
    可见性:volatile、synchronized、Lock
    有序性:Happen-before原则

  14. 多线程锁的升级原理是什么
    不了解,https://blog.csdn.net/meism5/article/details/90321826 文章讲的挺好,可以作为了解

  15. 什么是死锁
    由两个或两个以上的线程互相持有对方需要的资源而导致线程等待无法向下进行称为死锁

  16. 怎么防止死锁
    加锁顺序、加锁时限、死锁检测

  17. ThreadLocal是什么?有哪些使用场景
    ThreadLocal为每个线程都创建一个独立的副本,所以每个线程修改自己的副本,而不会影响其他线程的副本;
    测试代码:
    public static void main(String[] args) {
    final ThreadLocal NUM_THREAD = new ThreadLocal() {
    @Override
    protected Integer initialValue() {
    return 0;
    }
    };
    Thread thread1 = new Thread(new Runnable() {
    @Override
    public void run() {
    for (int i = 0; i <= 3; i++) {
    NUM_THREAD.set(NUM_THREAD.get() + 1);
    System.out.println("线程1: " + NUM_THREAD.get());
    }

       }
    

    });
    Thread thread2 = new Thread(new Runnable() {
    @Override
    public void run() {
    for (int i = 0; i <= 3; i++) {
    NUM_THREAD.set(NUM_THREAD.get() + 1);
    System.out.println("线程2: " + NUM_THREAD.get());
    }

       }
    

    });
    Thread thread3 = new Thread(new Runnable() {
    @Override
    public void run() {
    for (int i = 0; i <= 3; i++) {
    NUM_THREAD.set(NUM_THREAD.get() + 1);
    System.out.println("线程3: " + NUM_THREAD.get());
    }

       }
    

    });
    thread1.start();
    thread2.start();
    thread3.start();
    }
    运行结果:
    在这里插入图片描述
    互不影响
    底层实现原理:ThreadLocal的内部静态类ThreadLocalMap,该类的key为ThreadLocal的this引用,value即为变量副本;ThreadLocal的操作都是对当前线程的副本的操作
    在这里插入图片描述
    这篇文章写的不错,可以看一看帮助理解
    https://www.cnblogs.com/xzwblog/p/7227509.html

  18. synchronized和volatile的区别是什么
    synchronized:原子性、有序性、可见性,修饰于变量、方法、类、同步代码块,线程阻塞
    volatile:有序性和可见性,修饰于变量,线程不阻塞

  19. synchronized和Lock有什么区别
    synchronized:java的内置关键字,锁的获取和释放自动进行,不可重入
    Lock:接口,索的获取和释放需要手动进行,可重入

  20. synchronized和ReentrantLock区别是什么
    synchronized:java的内置关键字,锁的获取和释放自动进行,不可重入
    ReentrantLock:Lock的实现,索的获取和释放需要手动进行,可重入

  21. atomic的原理
    利用CAS(Conmpare And Swap)原理,当线程要写入数据时,先保存一份旧数据,在真正要写入数据时,用保存的旧数据与主内存中的数据进行对比,如果相同则写入,如果不同,则重新尝试

发布了8 篇原创文章 · 获赞 0 · 访问量 123

猜你喜欢

转载自blog.csdn.net/weixin_38647628/article/details/104697581