多线程考核点【重点】
1.什么是进程?什么是线程?
进程是资源分配的基本单位,是应用程序的执行实例。
线程是程序执行的最小单位,是进程的一个执行流,一个线程由多个线程组成的。
2.多线程优缺点?
优点:
1.多线程的可以提高计算机系统的CPU的利用率
2.多线程还可以改善程序的结构,将既长又复杂的进程分为多个线程,独立运行,利于理解和修改
缺点
1.对线程进行管理要求额外的 CPU开销
2.等候使用共享资源时造成程序的运行速度变慢
3.线程太多会导致控制太复杂,最终可能导致死锁
3.什么是并发?什么是并行?
并发是指两个或多个事件在同一时间间隔发生
并行是指两个或者多个事件在同一时刻发生
4.Java中实现线程方式?【重点】
继承Thread类,重写run方法,直接创建该类的对象
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadDemo threadDemo = new ThreadDemo();
threadDemo.start();
}
class ThreadDemo extends Thread{
@Override
public void run() {
System.out.println("ThreadDemo run");
}
}
实现Runnable接口,实现run方法,使用Runnable对象作为参数创建Thread对象
public static void main(String[] args) throws ExecutionException, InterruptedException {
Thread threadDemo2 = new Thread(new ThreadDemo2());
threadDemo2.start();
}
class ThreadDemo2 implements Runnable{
@Override
public void run() {
System.out.println("ThreadDemo2 run");
}
}
实现Callable接口,实现call方法,使用Callable对象创建FutureTask对象,再用FutureTask对象创建Thread对象,可以使用FutureTask对象获取返回值
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> futureTask = new FutureTask<Integer>(new ThreadDemo3());
Thread threadDemo3 = new Thread(futureTask);
threadDemo3.start();
Integer integer = futureTask.get();
System.out.println(integer);
}
class ThreadDemo3 implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("ThreadDemo3 run");
return 3;
}
}
5.runnable和callable区别?
runnable实现run方法,没有返回值,抛出运行时异常,无需处理
callable实现call方法,有返回值,抛出异常,需要异常处理
6.守护线程和普通线程区别?
守护线程是一种特殊线程,
应用程序必须运行完所有的用户线程才可以退出。
应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的守护线程在应用程序退出时都会自动结束。
7.线程常用方法
start()://启动当前线程并调用线程的run()方法
currentThread():///静态方法,放回当前代码执行的线程
yield()://释放当前cpu的执行权
join()://在线程A中调用线程B的join方法,使得线程A进入阻塞状态,直到线程B完全执行完,线程A才结束阻塞状态,实行线程的串行执行。
stop()://已过时,在执行此方法时,强制结束该线程
sleep(long long millis);//让当前线程睡眠指定的millis毫秒时间内(睡眠即当前线程为阻塞状态)
interrupt();//打断线程休眠
isAlive()//判断当前线程是否还存活
setPriority();//改变线程的优先级
8.run和start区别?
run是Thread类中的方法,是线程的默认要执行的方法,不会开启线程
start是实现Runnable要写的方法,start方法会开启一个线程,并在该线程中执行run方法
9.线程状态是什么?
线程的状态值线程的运行情况
线程的六种状态
1.新建(NEW):创建后尚未启动的线程处于这种状态。
2.就绪(RUNNABLE):线程正在执行代码,就处于该状态。
3.阻塞状态(BLOCKED):一个线程获取synchronized锁对象失败,就处于该状态。
4.等待(WAITING):一个线程获取Lock锁对象失败,就处于该状态。
5.计时等待状态(TIMED_WAITING):线程正在执行sleep方法,就处于该状态。
6.消亡状态(TERMINATED):线程把任务执行完毕后,就处于该状态。
10.线程的sleep()方法和yield(方法有什么不同?
sleep让线程变为阻塞状态,不释放线程锁,抛异常(异常)
yield让线程回到就绪状态,释放线程锁
11.什么是死锁、如何避免
系统中供多个进程共享的资源的数目不足以满足全部进程的需要,导致所有进程都无法执行的现象。
避免死锁:
不要嵌套锁
12.sleep和wait区别?线程协作(线程经典案例–Object(wait(n),notify(),notifiyAll()))
sleep是Thread类的方法,wait是Object类中定义的方法
sleep可以在任何地方调用,wait方法只能在synchronized修饰的方法中调用
sleep有时间限制,wait没有时间限制,必须要用notify唤醒线程。
13.什么是 ThreadLocal?【重点】
本地线程变量,实现线程变量的私有化,其中有一个ThreadMap变量,是线程私有的。
弱引用。
即数据存储在线程自己的局部变量中,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或着组件之间一些公共变量的传递的复杂度,主要用于解决数据访问的竞争。
14.ThreadLocal是否会内存泄漏?
会
TreadMap中当弱引用key被释放的时候,value强引用不会被释放,造成内存泄漏
15.解释—下强引用、软引用、弱引用、虚引用?
强引用(StrongReference):一般指的是对像被new出来,强引用一般不会被jvm收回,但会报OutOfMemory(内存不足)。
软引用(SoftReference):软引用相对来说弱于强引用,当内存足够的时候不会被GC回收,但内存不足时,再试图回收软引用,通过软引用可以做临时缓存。
弱引用(WeakReference):区别于软件引用是生命周期更短,当GC回收启动发现弱引用不管内存满不满,都会被直接回收。
虚引用(PhantomReference):这个引用也有人叫幻引用,也很明显,引用一个不存在,随时会被干掉,算是所有引用中最容易被干掉的。
16.为什么要使用线程池?
线程池可以降低资源消耗、提高响应速度、方便管理;实现线程的复用、可以控制最大并发数、可以管理线程
17.execute()和submit()区别?
- execute只能提交Runnable类型的任务,没有返回值,而submit既能提交Runnable类型任务也能提交Callable类型任务,返回Future类型。
- execute方法提交的任务异常是直接抛出的,而submit方法是是捕获了异常的,当调用FutureTask的get方法时,才会抛出异常。
18.shutdown()和shutdownNow()区别?
shutdown只是将线程池的状态设置为SHUTWDOWN状态,正在执行的任务会继续执行下去,没有被执行的则中断。
shutdownNow则是将线程池的状态设置为STOP,正在执行的任务则被停止,没被执行任务的则返回。
19.volatile的作用和特性?【重点】
当一个变量被声明为volatile时,线程在写入变量时不会把值缓存在寄存器或者其他地方,而是会把值刷新回主内存。
当其他线程读取该共享变量时,会从主内存重新获取最新值,而不是使用当前线程的工作内存中的值。
特性:保证可见性、保证有序性、不能保证原子性操作
20.volatile和synchronized区别?【重点】
volatile关键字是对变量进行上锁,锁住的是单个变量,保证有序性但不保证原子性
synchronized可以对变量和方法以及代码块进行上锁,保证有序性,原子性
21.什么是乐观锁?什么是悲观锁?
乐观锁访问数据时不会对数据进行上锁,修改数据时才会上锁
悲观锁访问数据、修改数据时都会对数据上锁
22.什么是GC、作用是什么
GC是垃圾回收器
自动对内存进行管理,自动销毁不被引用的对象,防止内存泄漏
23.GC回收的区域在哪里?
GC垃圾回收作用区域集中于堆和方法区。
25.JVM内存结构
JVM分为五个区域
Java虚拟机栈:用于存储局部变量表、操作数栈、动态链接、方法出口等信息。(栈里面存储的是的地址,实际指向的是堆里面的对象)
本地方法栈:里面并没有我们写的代码逻辑,存储c++的native方法运行时候的栈区。
程序计数器:(指向当前程序运行的位置)它是一块很小的内存空间,主要用来记录各个线程执行的字节码的地址,例如,分支、循环、线程恢复等都依赖于计数器。
堆:Java虚拟机中最大的内存空间,被所有的线程共享,几乎所有的对象实例都在这里分配实例。
方法区(Java8叫元空间):用于存放已被虚拟机加载的类信息、常量和静态变量等数据。
26.GC常用算法
引用计数算法
根搜索算法
标记-清除算法
复制算法
27.常用的JVM调优的参数都有哪些?(了解)
-Xms10g :JVM启动时申请的初始堆内存值
-Xmx20G :JVM可申请的最大Heap值
-XX:+PrintGC :打印GC日志
-XX:+PrintGCDetailsGC :时的详细堆信息
-XX:+UseConcMarkSweepGC :启用CMS
-XX:ParallelCMSThreads :设置CMS线程数量