线程知识点总结
线程知识点总结
1.什么是线程?
答:线程是指程序中的一个执行流。
2. 什么是多线程?
答:多线程是指程序中包含多个执行流。
3.进程和线程的区别?
答:进程是指正在执行的程序,线程是程序中的一个执行流。一个进程可以包含多个线程。
4.什么情况下会用到多线程?
答:并行执行任务的时候。对tomcat而言,每一个进来的请求都需要一个线程。当有并发访问的时候,就会用到多线程。
5.我们为什么要使用多线程?
答:使用多线程是为了尽可能多的去利用CPU的资源,提高效率。
6.使用多线程就一定会提高CPU的利用率(提高效率)吗?
答:不一定。多线程如果使用得当会提高CPU的利用率,但如果使用不当的话,不仅不能提高CPU的利用率,反而会降低。因为多线程的操作流程要比单线程的多得多,比如线程的创建和销毁,线程之间的调度,CPU执行权的切换等等,而单线程是没有这些问题的,所以使用多线程不一定就会提高CPU的利用率。
7. 在使用多线程的时候,什么情况下容易产生线程安全问题?
答:多个线程操作同一个资源时,即生产者消费者问题,会产生线程安全问题。
8.什么是线程安全问题?
答:线程安全问题是指多个线程访问同一资源,产生的结果不确定的情况。解决线程安全问题的方法是同步。
9.多线程实现同步的方式有哪些?
答:加synchronized关键字;使用Lock接口。
10. synchronized关键字和Lock接口有什么区别?
答:1.sychronized是关键字,Lock是接口;
2.synchronized关键字在发生异常时候会自动释放锁,因此不会出现死锁;而lock发生异常时,不会自动释放锁,可能出现死锁。
3.Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
4.lock可以通过trylock来知道有没有获取锁,而synchronized不能。
11.多线程有几种实现方案,分别是哪几种?
答:三种。
继承Thread类,重写run()方法;
实现Runnable接口,重写run()方法;
实现Callable接口,重写call()方法。
12.什么是死锁?
答:死锁指的是两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象。
13.用代码写一个死锁。
14.启动一个线程是run()还是start()?它们的区别?
答:用start()方法来启动一个线程;
区别:
run():封装了被线程执行的代码,直接调用仅仅是普通方法的调用
start():启动线程,并由JVM自动调用run()方法
15.sleep()和wait()方法的区别
答:sleep():属于Thread类;必须指定时间, 计时时间一到,线程会自动被唤醒;不释放锁;可以在任何地方使用;
wait():属于Object类;可以不指定时间,也可以指定时间需要被外界唤醒;释放锁;只能在同步代码块中使用。
16.为什么wait(),notify(),notifyAll()等方法都定义在Object类中
答:因为这些方法的调用是依赖于锁对象的,而同步代码块的锁对象是任意锁。而Object代表任意的对象,所以,定义在这里面。
17.线程的生命周期图
答:新建 -- 就绪 -- 运行 -- 死亡
新建 -- 就绪 -- 运行 -- 休眠/等待 -- 就绪 -- 运行 -- 死亡
18.线程的6种状态?(几种状态有多种版本,我统一一下我的版本)
答:新建、就绪、运行、休眠、等待、死亡。
注意:休眠和等待,有人统一为阻塞。
就绪:线程具有CPU的执行资格,但没有CPU的执行权。(就像一名参赛选手,有比赛的资格,但还没有轮到他上场)
休眠/等待:线程放弃了CPU的执行资格
面试题:(扩展)
1.就绪状态和阻塞(休眠、等待)状态有什么区别?
答:就绪状态有CPU的执行资格,但是没有CPU的执行权,这一状态程序员无法控制。
阻塞状态没有CPU的执行资格,这一状态程序员可以控制。
2. 休眠状态(sleep)和等待状态(wait)有什么区别?这一个问题,通常这样问:sleep()和wait()方法的区别?
答:sleep():属于Thread类;必须指定时间, 计时时间一到,线程会自动被唤醒;不释放锁;可以在任何地方使用;
wait():属于Object类;可以不指定时间,也可以指定时间,需要被外界唤醒;释放锁;只能在同步代码块中使用。
19.终止线程的方法有哪些?
答:Thread类提供了两个方法:stop(),suspend(),都可以用来终止线程。二者的区别是:
当调用Thread.stop()来终止线程时,会释放锁,可能会导致程序执行的不确定性。
当调用Thread.suspend()来终止线程时,不会释放锁,可称之为挂起线程,容易发生死锁。
通常情况下,结束线程最好的方法是让线程自行结束进入Dead状态,即提供某种方式让线程能够自动结束run()方法的执行,例如设置一个flag标志来控制循环是否执行,通过这种方法来让线程离开run()方法从而终止线程。
System.exit()也可以终止线程。
20.什么是守护线程?
答:java提供了两种线程:守护线程和用户线程。
守护线程在后台服务于用户线程,是用户线程的“保姆”。
GC属于守护线程。
21.Join()方法的作用?
答:将两个线程合并,用于实现同步功能。
22.什么是线程同步?
答:当多个线程访问同一资源时,为了防止线程安全问题的发生,需要线程同步。实现线程同步的方法一般有两种:加sychronized关键字、使用Lock接口。
Sychronized关键字又可以是同步代码块和同步方法,Lock接口是JDK1.5之后的升级版本。
要想实现线程同步,必须要获得一个线程对象的锁。
23.你了解多线程中的volatile关键字吗?简单介绍一下。
答:volatile关键字是通过同步变量来解决内存可见性问题的。内存可见性问题指得是当多个线程操作共享数据时,彼此不可见的问题。
在多线程中,共享变量会放在主内存中,每个线程在创建的时候都会创建一个属于自己的独立的缓存区,它会将主内存中的变量保存一份在自己的缓存中作为变量副本,这样一来就很容易造成线程间彼此保存的变量副本是不一致的,即彼此不可见。 而当一个变量被volatile修饰后,该变量就不能被缓存到各个线程的内存中,只在主内存中保留一份,这样一来,所有线程操作的都是同一份变量,这就确保了该变量在内存中的可见性。
24.你了解多线程中的synchronized关键字吗?简单介绍一下。
答:当多个线程操作同一资源的时候,容易产生线程安全问题,解决线程安全问题的方法是同步,synchronized关键字是同步的一种方式。它可以加在代码块上构成同步代码块,加在方法上构成同步方法,用synchronized关键字解决同步问题需要锁对象,该锁对象可以是任意对象,但要保证唯一。
25.volatile相较于synchronized的区别是什么?
答:1.同步的对象不同,volatile同步的是变量,synchronize同步的是代码块或方法;2.synchronized的关键字可以保证元素的“互斥性”和“唯一性”,而volatile不可以。
26.什么是线程池?
答:线程池就是一个可以容纳多个线程的容器,里面的线程处于等待状态,避免了频繁创建和销毁线程造成的系统资源浪费。
27.为什么要使用线程池?
答:在java开发中,如果每一个请求的到来都需要创建一个新线程,那么对于系统资源的浪费是非常严重的,我们需要想一个办法来尽可能减少创建和销毁线程的次数。于是线程池应运而生了。线程池就是一个可以容纳多个线程的容器,里面的线程处于等待状态,用的时候直接从线程池中拿,不用的时候再放回到线程池中去,避免了频繁创建和销毁线程造成的系统资源浪费。
28.线程池中ThreadPoolExecutor的参数有哪些?
答:核心线程池大小(corePoolSize)、最大线程池大小(maximumPoolSize)、workQueue(任务队列)、保持存活时间(keepAliveTime)等。
29.线程池的种类有哪些?
答:4种。固定线程池(FixedThreadPool)、可缓冲线程池(CacheThreadPool)、单线程池(SingleThreadPool )、定时器线程池(newScheduledThreadPool)。
30.线程池的执行流程是什么?
答:线程池按以下行为执行任务
1. 当线程数小于核心线程数时,创建线程。
2. 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
3. 当线程数大于等于核心线程数,且任务队列已满
若线程数小于最大线程数,创建线程
若线程数等于最大线程数,抛出异常,拒绝任务