栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

【Java面试题 持续整理中~】

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Java面试题 持续整理中~】

文章目录
    • 多线程
      • 1. 进程和线程的关系
      • 2. 创建线程的几种方式
      • 3. 继承Thread类和实现Runnable两种方式的区别
      • 4. 启动线程使用start还是run
      • 5. 多线程的执行是什么顺序
      • 6. sleep和wait区别
      • 7. 线程的生命周期
      • 8. 什么是公平锁和非公平锁?
      • 9. synchronized和同步锁的区别?
      • 10. 线程同步的三大特征:
      • 11. synchronized与volatile的区别?
      • 12. 悲观锁和乐观锁?
      • 13. 线程的等待和通知机制如何实现
      • 14. 什么是生产者消费者模式,解决了什么问题,实现的思路是什么?
      • 15. 阻塞队列是什么,有什么作用?
      • 16. ThreadLocal是什么,有什么作用?
      • 17. 讲讲强软弱虚引用
    • 线程池
      • 1. 线程池的作用,常见的线程池有哪些?
      • 2. 解释线程池的几个参数
      • 3. 线程池如何进行配置
      • 4. 讲讲对线程池原理的理解
    • 网络通信
      • 1. 网络七层模型
      • 2. 三次握手和四次挥手
      • 3. 为什么要三次握手?(扩展)
      • 4. Socket编程的流程

多线程 1. 进程和线程的关系
  • 进程 是运行起来的程序,是操作系统分配资源cpu内存的最小单元,
  • 线程 是CPU分配和调度的最小单元,一个进程可以由一个或多个线程组成。
  • 区别:
    • 内存方面:
      进程需要的资源更多(内存(堆、方法区、本地方法区)),线程更轻量级(栈、程序计数器)
  • 创建和销毁:
    进程需要更多的时间和资源,线程更快。
  • 通信方面:
    进程之间通讯比较麻烦(RPC、网络),线程之间通讯更容易(通过线程共享的内存空间)
2. 创建线程的几种方式
  • 继承Thread类,重写run方法。
  • 实现Runnable接口,实现run方法;
  • 实现Callable接口,实现Call方法,创建一个FutureTask对象;
3. 继承Thread类和实现Runnable两种方式的区别
  • java支持单继承多实现,继承Thread类之后无法继承其他类,实现接口无限制;
  • 继承Thread类可以不用重写run方法,实现接口必须重写run方法;
  • 实现Runnable接口可以使用lambda表达式,语法更加简洁。
4. 启动线程使用start还是run
  • 使用run方法是在主线程中执行,使用start方法才是开启并执行线程。
5. 多线程的执行是什么顺序

多线程的执行是抢占式的,线程会去抢占cpu,抢到后执行自己的指令,执行过程中可能会被其他线程抢占,当切换回原来的线程时,线程通过自己的程序计数器来继续执行代码。

6. sleep和wait区别
  • 调用对象不同,wait是锁对象调用,sleep是当前线程调用。
  • 唤醒机制不同,线程进入wait后,要通过锁对象notify/notifyAll唤醒,sleep当时间结束之后自动唤醒。
  • 锁释放不同,线程进入wait后,会自动释放锁,线程sleep不会释放锁。
7. 线程的生命周期
  • new新建 -> start就绪/准备 -> 运行 -> wait…阻塞 -> 死亡
8. 什么是公平锁和非公平锁?
  • 公平锁:等待锁时间长的线程,更容易获得锁;
  • 非公平锁:等待锁时间长和短的线程,获得锁的几率相同。
9. synchronized和同步锁的区别?
  • 上锁:synchronized是自动上锁和解锁的,同步锁是手动完成的。
  • 性能:同步锁性能高于synchronized
  • 使用:synchronized使用简单,功能单一,同步锁提供更多方法,使用灵活。
10. 线程同步的三大特征:
  • 原子性:(一系列指令要么全部执行,要么全部不执行)
  • 可见性:(线程中的数据修改后,其他线程也可以读取最新的数据)
  • 有序性:(线程中的指令按顺序执行,不会出现乱序)
11. synchronized与volatile的区别?
  • 修饰的对象:synchronized修饰代码块或方法,volatile只能修饰变量
  • 保证的特性:synchronized保证原子性、可见性;volatile不能保证原子性,保证可见性和有序性
  • 性能:volatile是轻量级的线程同步方式,性能更高
12. 悲观锁和乐观锁?
  • 悲观锁:对于并发间操作产生的线程安全s问题持悲观状态,悲观锁认为竞争总会发生,因此每次对资源进行操作时,都会给资源加锁。
  • 乐观锁:对于并发间操作产生的线程安全问题持乐观状态,乐观锁认为竞争不会发生,因此不持有锁,使用版本号和CAS机制解决:
    • 版本号机制:对资源设置版本,每次修改后更新版本,修改后与之前版本比较,相同提交,不同不提交。
    • CAS机制:CompareAndSwap:通过内存偏移量获取数据原始值,通过原始值计算预期值和实际值比较,相同更新,不同不更新。进入循环等待状态,直到比较相等。
13. 线程的等待和通知机制如何实现

可以通过锁对象调用Object类的方法(如果不是锁对象会出现illegalMonitorStateException):

  • wait() 让当前线程等待,直到被通知
  • wait(long) 让线程等待,知道被通知或超时
  • notify() 随机唤醒一个线程
  • notify() 唤醒所有线程
14. 什么是生产者消费者模式,解决了什么问题,实现的思路是什么?

是一种设计模式,解决了两点(线程、进程、服务器)之间的数据通信问题

  • 生产数据的点叫生产者,使用数据的点叫消费者,生产者和消费者之间存在速度不一致的问题,生产者速度过快,消费者速度慢,会浪费大量资源。反之,生产者慢,消费者速度快,消费者浪费时间请等待。
  • 解决的问题:
    1. 解耦,生产者和消费者之间加入缓冲区,不需要直接调用
    2. 忙闲不均,协调生产者和消费者之间的速度。
    3. 节约资源,提高性能,减少生产者的资源浪费,减少消费者的等待时间。
  • 实现思路:
    1. 设计缓冲区,设计临界值;
    2. 生产者生产的数据存入缓冲区,如果缓冲区达到临界值,生产者就等待;否则就通知消费者来消费。
    3. 消费者从缓存区取出数据,如果缓冲区空了,消费者等待;否则就通知生产者继续生产。
15. 阻塞队列是什么,有什么作用?

是一种特殊的集合,会自动阻塞队列添加和删除数据的线程,也可以自动通知。

16. ThreadLocal是什么,有什么作用?

线程局部变量,也是解决线程同步问题的一种方式。

  • 锁机制,多个线程排队访问一个资源,以时间换空间。
  • ThreadLocal多个线程并发访问自己的独立资源,以空间换时间。
  • 每个线程内部有Map集合ThreadLocalMap,获得数据时候返回当前线程的Map集合,局部变量是保存到当前线程的Map中的
17. 讲讲强软弱虚引用
  • 强引用(strongReference):一般情况下创建的对象都具有强应用,强引用不会被垃圾回收器回收,即使空间不足,jvm也不会回收它它,只会抛出OutOfMemoryError,使线程异常终止。如果想要终止强引用和某个对象之间的引用,可以显示的将引用赋值为null,这样jvm就会在合适的时间回收该对象。
  • 软引用(softReference):软引用只有在内存不够的情况下才会被回收,一般用于缓存。
  • 弱引用(WeakReference):弱引用在JVM进行垃圾回收时,不论空间是否充足都会回收。可以用来缓存临时数据。
  • 虚引用(PhantomReference):形同虚设,任何情况都会被垃圾回收机制回收,主要用于跟踪垃圾回收器的活动。
线程池 1. 线程池的作用,常见的线程池有哪些?

线程是一种有限的宝贵的系统资源,创建线程需要很多时间和系统资源,需要对线程进行回收利用,降低对系统资源的消耗,提升服务器的执行效率。

顶层接口:Executor,有一个execute(Runnable)将任务交给线程池执行。

子接口ExecutorService,有:shutdown() 和 shutdwnNow()方法停止线程池。

ExecutorService的子接口:scheduleExecutorService:

  • 在固定的延迟时间后执行

    scheduleWithFixedDelay(执行的Runnable任务,初始的延迟,延迟,时间单位)
    
  • 在固定的周期执行

    scheduleAtFixedRate(执行的Runnable任务,初始的延迟,周期,时间单位)
    

    工具类:

    Executors 提供了几个静态方法,帮助方便的创建线程池

    线程池类型说明
    ExecutorService newCachedThreadPool()创建线程个数不限的线程池
    ExecutorService newFixedThreadPool(int)创建个数固定的线程池
    ExecutorService newSingleThreadExecutor()创建单个线程的线程池
    ScheduledExecutorService newScheduledThreadPool(int)创建可以调度的线程池
    ExecutorService newWorkStealingPool()创建工作窃取机制的线程池
2. 解释线程池的几个参数
参数说明
corePoolSize核心线程数(线程池初始的线程数,核心线程会一直保留)
maximumPoolSize最大线程数(线程池最大线程数,非核心线程可能被干掉)
keepAliveTime保持存活的时间(非核心线程如果在此时间内没有接收任务,就可能被干掉)
unit时间单位
BlockingQueue用于保存任务的阻塞队列
ThreadFactory线程工厂,用于创新线程
RejectedExecutionHandler拒绝策略(任务数超过最大线程数,拒绝执行任务的方式)
3. 线程池如何进行配置

优化配置:
核心线程数 和cpu核心数以及任务数量和执行时间相关
核心线程数 = cpu核心数 * n
n >= 1 上限和任务数以及执行时间相关
本机的cpu核心数 Runtime.getRuntime().availableProcessors();
最大线程数
最大线程数和核心线程数相同,减少系统创建线程和销毁线程的时间和资源,提高性能
keepAliveTime
如果最大线程数和核心线程数相同,可以设置为0;
否则可以尽量大一点,减少系统创建线程和销毁线程的时间和资源
BlockingQueue
设置为LinkedBlockQueue,任务经常添加和删除时,性能更高
设置为SynchorousQueue,能处理的任务数更多,吞吐量更高(每秒处理请求数)

4. 讲讲对线程池原理的理解

步骤:
1) 通过线程池的execute执行任务
2) 通过调用线程池的addWorker方法添加工作线程
3) 同时把Runnable执行任务添加到workQueue中
4) 创建Worker添加到HashSet中,Worker中包含线程
5) 启动Worker中的线程
6) 线程调用runWorker方法
7) runWorker中判断任务不为空就执行任务
8) 任务如果为空,就调用getTask()方法取任务
9) 循环不断调用workerQueue阻塞队列的take()方法
10) 任务队列为空就自动阻塞当前线程,直到任务队列不为空唤醒线程去执行任务

网络通信 1. 网络七层模型

​1) 物理层,底层硬件
2) 数据链路层,通信的介质
3) 网络层,寻址和路由, IP协议
4) 传输层,连接和数据通信,TCP协议UDP协议
5) 会话层,管理会话
6) 表示层,处理数据格式、加密
7) 应用层,程序之间的通信,http协议ftp协议smtp协议pop3协议

2. 三次握手和四次挥手
3. 为什么要三次握手?(扩展)

1.一次不行,服务端没有应答
2.二次不行,避免重复连接,客户端发送同步请求后,因为网络问题,没有及时达到服务端,重复发送请求,服务端应答后可能出现重复连接的情况。必须有三次,可以确定前面的历史报文,确认是之前的请求,再继续连接。

4. Socket编程的流程

1.1服务器端
(1) 创建ServerSocket对象,绑定监听端口;
(2) 通过accept()方法监听客户端请求;
(3) 连接建立后,通过输入流读取客户端发送的请求信息;
(4) 通过输出流向客户端发送相应信息;
(5) 关闭响应资源。

1.2 客户端
(1) 创建Socket对象,指明需要连接的服务器地址和端口;
(2) 连接建立后,通过输出流向服务器端发送请求信息;
(3) 通过输入流获取服务器端返回的响应信息;
(4) 关闭响应资源。

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1039033.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号