1.创建线程池
1)newCacheThreadPool 创建一个可缓存的线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程
2)newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
3) newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行
4) newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
2.线程池状态
线程池有5种状态:Running、ShutDown、Stop、Tidying、Terminated
3.submit() execute()
接收的参数不一样;submit有返回值,而execute没有;submit方便Exception处理
4.多线程锁的升级原理
4.怎么避免死锁?
尽量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),设置超时
时间,超时可以退出防止死锁。
尽量使用 Java. util. concurrent 并发类代替自己手写锁。
尽量降低锁的使用粒度,尽量不要几个功能用同一把锁。
尽量减少同步的代码块。
加锁顺序(线程按照一定的顺序加锁)
5.ThreadLocal
解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题
这个类能使线程中的某个值与保存值的对象关联起来。ThreadLocal 提供了 get 与 set 等访问接口或方法,这些方法为每个使用该变量的线程都存有一份独立的副本,因此get 总是返回由当前执行线程在调用 set 时设置的最新值
在Java的多线程编程中,为保证多个线程对共享变量的安全访问,通常会使用synchronized来保证同一时刻只有一个线程对共享变量进行操作。这种情况下可以将 类变量放到ThreadLocal类型的对象中,使变量在每个线程中都有独立拷贝,不会出现一个线程读取变量时而被另一个线程修改的现象。最常见的ThreadLocal使用场景为用来解决数据库连接、Session管理等
6.简述synchronized原理
Java 虚拟机中,synchronized 支持的同步方法和同步语句都是使用 monitor 来实现的。 每个对象都与一个 monitor 相关联,当一个线程执行到一个 monitor 监视下的代码块中的第一个指令时,该线程必须在引用的对象上获得一个锁,这个锁是 monitor 实现的;
当并发线程执行 synchronized 修饰的方法或语句块时,先进入_EntryList 中,当某个线程获取到对象的 monitor 后,把monitor 对象中的_owner 变量设置为当前线程,同monitor 对象中的计数器_count 加 1,当前线程获取同步锁成功;
当 synchronized 修饰的方法或语句块中的线程调用 wait()方法时,当前线程将释放持有的 monitor 对象,monitor 对象中的_owner 变量赋值为 null,同时,monitor 对象中的_count 值减 1,然后当前线程进入_WaitSet 集合中等待被唤醒。
7.简述atomic原理
atomic ioperation 不能被中断的一系列操作,在多处理上实现原子操作有些复杂
处理器实现原子操作的方式由两种:
1)通过使用总线锁来保证原子性。如多个处理器同时对共享变量进行操作,使用总线锁,可以保证只有一个处理器在操作共享内存,其他处理器无法的请求将被阻塞。
2)通过缓存锁定保证原子性。总线锁锁定处理器和内存之间的通信,开销很大,而有时只需要锁定某个变量即可
java 通过锁和 CAS 循环来实现原子操作
java 的 concurrent 包的源代码实现,有一个通用化的实现模式:
首先,声明共享变量为 volatile;然后,使用 CAS 的原子条件更新来实现线程之间的同步;同时,配合以 volatile 的读/写和 CAS 所具有的 volatile 读和写的内存语义来实现线程之间的通信。
8.CAS实现原理
CAS (Compare and Swap) 比较并交换
先提前一步获取旧值,然后进入此方法比较当下的值是否与旧值相同,如果相同,则更新数据,否则退出方法,重复一遍刚才的动作。由此可见,CAS 方法是非堵塞的。CAS 方法需要三个参数,变量内存值、旧的预期值、数据更新值。
9.OSI七层模型
应用层:网络服务与最终用户的一个接口。
表示层:数据的表示、安全、压缩。
会话层:建立、管理、终止会话。
传输层:定义传输数据的协议端口号,以及流控和差错校验。
网络层:进行逻辑地址寻址,实现不同网络之间的路径选择。
数据链路层:建立逻辑连接、进行硬件地址寻址、差错校验等功能。
物理层:建立、维护、断开物理连接
10.TCP协议
CP/IP 协议栈是一系列网络协议的总和,是构成网络通信的核心骨架,它定义了电子设备如何连入因特网,以及数据如何在它们之间进行传输
TCP/IP 协议采用 4 层结构,分别是应用层、传输层、网络层和链路层,每一层都呼叫它的下一层所提供的协议来完成自己的需求
三次挥手:
四次握手:
11.Tcp粘包
概念:发送方发送的多个数据包,到接收方缓冲区首尾相连,粘成一包,被接收
原因:TCP 协议默认使用 Nagle 算法可能会把多个数据包一次发送到接收方。应用程读取缓存中的数据包的速度小于接收数据包的速度,缓存中的多个数据包会被应用程序当成一个包一次读取
解决方法:发送方使用 TCP_NODELAY 选项来关闭 Nagle 算法;数据包增加开始符和结束,应用程序读取、区分数据包;在数据包的头部定义整个数据包的长度,应用程序先读取数据包的长度,然后读取整个长度的包字节数据,保证读取的是单个包且完整
12.UDP TCP
13.反射
主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
在 Java 运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法
Java 反射机制主要提供了以下功能:在运行时,判断任意一个对象所属的类;构造任意一个类的对象;判断任意一个类所具有的成员变量和方法;调用任意一个对象的方法;调用任意一个对象的方法。
14.获得一个类的类对象
类.class;对象.getClass();Class.forName("java.lang.String")
15.序列化 反序列化
序列化:将 Java 对象转换成字节流的过程 类实现 Serializable 接口,这个接口没有需要实现的方法,实现 Serializable 接口是为了告诉 jvm 这个类的对象可以被序列化。
反序列化:将字节流转换成 Java 对象的过程
当 Java 对象需要在网络上传输 或者 持久化存储到文件中时,就需要对 Java 对象进行序列化处理。
16.动态代理
动态代理:在运行时,创建目标类,可以调用和扩展目标类的方法。
Java 中实现动态的方式:JDK 中的动态代理 和 Java 类库 CGLib。
应用场景如:统计每个 api 的请求耗时;统一的日志输出; 校验被调用的 api 是否已经登录和权限鉴定;Spring 的 AOP 功能模块就是采用动态代理的机制来实现切面编程
17.类加载
JVM中类的装载是由类加载器和它的子类来实现的,把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的class对象