java多线程常见面试题

1、线程和进程的区别

  1. 本质区别: 进程是一个程序的实例,是操作系统资源分配的最小单位;线程是任务调度与执行的最小单位
  2. 包含关系: 进程至少由一个线程组成,线程可看做轻量级进程
  3. 资源开销: 进程有自己的资源可以单独执行,进程之间的切换会有较大的开销;线程不独有资源,共享着进程的资源,每个线程有自己的栈和程序计数器,线程切换开销小。
  4. 健壮影响: 进程崩溃后一般不影响其他进程,线程崩溃后可能导致整个进程终止。
  5. 进程之间有父子关系;线程没有,但是有main方法作为主线程
  6. 因为线程之间存在共享资源的问题,可能存在对同一临界资源的争夺,存在同步和互斥关系。

2、什么是守护线程

守护线程和用户线程
用户线程就是正常意义上的线程,我们执行程序时默认的都是用户线程。
守护线程是指在程序运行的后台提供的通用线程,顾名思义,守护线程就是用户线程的守护者,基本构造和用户线程是一样的,除了一点:
当 jvm 关闭后守护进程才关闭。也就是说只要还存在用户线程时,守护线程就一定在。
例如:将一个线程设置为守护线程的方法就是在调用start()启动线程之前调用对象的setDaemon(true)方法。
守护线程的一个典型的例子就是垃圾回收器。只要JVM启动,它始终在运行,实时监控和管理系统中可以被回收的资源

@Slf4j
public class ThreadTest {
    public static void main(String[] args) {

        log.info("main Start ...");
        Thread myThread1 = new MyThread1();
        myThread1.setName("测试线程");
        myThread1.setDaemon(true);
        myThread1.start();
        log.info("main End ...");
    }
}

@Slf4j
class MyThread1 extends Thread{
    @Override
    public void run() {
        log.info(Thread.currentThread().getName()+"   begin....");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info(Thread.currentThread().getName()+"   end.....");
    }
}

在这里插入图片描述

3、并行和并发的区别

一个客观前提:一个CPU在某一时刻只能处理一个任务
并行:指在多核处理器下,每个cpu处理一个线程任务,形成了某一时刻物理上的多个线程同时进行
并发:指一个cpu快速切换处理多个线程任务,形成了用户状态上的多个线程同时进行,某一时刻物理上一个cpu仍旧只能处理一个线程。
在这里插入图片描述

4、CPU核数与并发数有关联吗?

物理上1 个cpu 某一时刻只能处理 1个线程,4核CPU最多可以同时跑4个线程(不考虑超线程),超线程技术简单理解为这个技术可以把1个CPU当成2个CPU用。

5、创建线程的几种方式 总结描述

  1. 继承 Thread 重写 run 方法;
  2. 实现 Runnable 接口,重写run 方法;
  3. 实现 Callable 接口 + Future 创建有返回值的线程。
  4. 线程池创建线程

6、线程池的了解 线程池学习

7、Java 中如何保证线程安全

  1. 使用线程安全的类。例如 package java.util.concurrent;
  2. 使用自动锁 synchronized synchronized 学习了解
  3. 自定义锁

8、Java 如何避免死锁问题

在我们解决互斥问题时,我们会在临界区加上锁,那么就会存在这样的问题,当一个线程已经获取了锁,还没有进行释放该锁,又尝试获取再次获取锁,很明显这把锁已经被自己占用了,还没有来的及释放,再次获取锁时一定会阻塞,直到等到锁,那么,既不能释放拥有的锁,也不可获得当前的锁,该线程就会一直阻塞,我们称类似于这种状态为死锁状态。

死锁的造成原因的必要条件是线程获取锁顺序不当。
进程没有及时的释放锁

  1. 一个线程获取两次锁 (线程获取 A 锁之后,未释放,再次尝试获取锁)

  2. 多个线程尝试交叉式获取锁,n个进程n把锁,都尝试获取对方的锁(线程 1 获取 A 锁,线程2获取 B锁,线程 1 尝试获取 B 锁,线程2 尝试获取 A 锁。)

  3. 使用线程安全的类。例如 package java.util.concurrent;

  4. 避免使用多个锁,减少嵌套锁的使用

  5. 合理分配资源的使用顺序

  6. 使用定时锁,使用死锁检测工具

9、synchronized 和 volatile 的区别

  1. volatile 只能修饰变量;synchronized 可以修饰方法、代码块、类
  2. volatile 原理是内存可见,每次访问变量时都从主存刷数据;synchronized 则是获取对象头的锁状态,进行加锁和解锁
  3. volatile 支持内存可见,不支持原子性(除了基本类型的简单操作,例如 ++ 或者 --),synchronized 支持内存可见,也通过锁支持了原子性
  4. volatile 不会造成线程阻塞问题,但是 synchronized 因为加锁可能造成线程阻塞问题

10、synchronized 和 Lock 的区别 TODO

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值