线程面试题话术

1、创建线程的方式

首先呢,Thread 类本质上是实现了 Runnable 接口,代表一个线程的实例。所以我们可以编写一个类,继承Thread类,或者直接实现Runnable接口,然后再重写下run方法就行了。启动线程的方式就是调用类里边的 start方法。start()方法是一个 native 方法,它的作用就是启动线程,线程会去执行 run()方法中的代码。

还有就是实现 Callable 接口,这个接口相当于是Runnable接口的增强版,他的执行代码的方法不是run方法了,是call方法,这个call方法可以有返回值,我们可以创建一个 FutureTask 类的实例对象,通过他的get()方法得到执行结果,不过这里定的执行结果需要跟FutureTask的泛型一致才行,并且call方法还可以抛出异常,通过这些,我们就能很明确的知道线程内部的执行状态

还有就是通过线程池来实现,线程池就是事先将多个线程对象放到一个容器中,当使用的时候就不用 new 线程而是直接去池中拿线程即可,节省了开辟子线程的时间,提高的代码执行效率。 一般创建线程池的话,都是使用个的Executors 类中提供的创建线程池的静态方法。他可以创建4种线程池,有

FixedThreadPool,创建固定大小的线程池,比如线程池容量是10,最多可以同时执行10个线程。

CachedThreadPool,创建一个可缓存的线程池,此线程池不会对线程池大小做限制,线程池大小完全依赖于JVM能够创建的最大线程大小,当然线程池里的线程是可以复用的,但是如果在高并发的情况下,这个线程池在会导致运行时内存溢出问题

ScheduledThreadPool,创建一个定时执行的线程池,里边提供了两个方法,FixRate和fixDelay,fixRate就是以固定时间周期执行任务,不管上一个线程是否执行完,fixDelay的话就是以固定的延迟执行任务,就是在上一个任务执行完成之后,延迟一定时间执行。

SingleThreadExecutor,创建一个单线程的线程池,这个线程池同时只能执行一个线程,可以保证线程按顺序执行,保证数据安全。

2、线程都有哪些方法

线程里的方法有很多,我给您说说我们常用的方法吧

wait方法呢就是线程等待,调用这个方法之后,线程进入 waiting 状态,只有等待通知notify或者notifyAll才会继续执行,这个时候 会释放对象的锁。因此呢,wait 方法一般用在同步方法或同步代码块中。

sleep线程睡眠,让当前线程休眠,此时线程处于阻塞的状态,当前线程进入timed-waiting状态

yield线程让步,我看源代码的意思是释放CPU资源,让其他线程抢夺CPU资源,实际用的时候,大概就是让当前线程先暂停,让其他线程先运行

join线程插队,我理解的呢就是让当前线程先运行,其他线程先等待,等运行完在执行其他线程

interrupt线程中断,这个就是中断当前线程的意思

notify唤醒线程,notifyAll唤醒所有线程

3、sleep和wait的区别

我之前写代码的时候也一直会用到这两个方法,我总结的区别大致分了三个方面

首先就是sleep不会释放锁,而wait会释放锁

接着呢就是sleep不会解除cpu占用,wait会释放cpu资源

然后还有就是sleep会导致线程阻塞,时间到了之后,线程继续向下执行,但是wait必须配合notify或者notifyAll来唤醒

4、介绍下你理解的线程中的锁

我理解的锁的话,就是在多个线程同时访问一个数据的时候,为了保证数据的安全性,我们需要对数据操作的代码进行加锁处理,一般来说这个锁需要是对所有线程是一致的,一般可以用静态变量来作为锁,这个锁用synchronized关键字来包裹着,当这段代码块执行完之后,释放锁,然后其他线程获取到这个锁之后,才能执行这段代码,通过锁的机制很好的保护了多线程下的数据安全

但是在用锁的时候,如果使用不当的话会导致死锁的问题,就是A线程等待B释放锁,B线程同时在等待A释放锁,这样的话就会导致两个线程相互等待,造成死锁,所以在使用的时候尽量避免多线程之间相互依赖锁的情况发生

还有对锁的分类的话,分为乐观锁和悲观锁

乐观锁的话就是比较乐观,每次去拿数据的时候,认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制或者CAS 算法实现。乐观锁在读操作比较多的场景比较适用,这样可以提高吞吐量,就像数据库提供的write_condition机制,其实都是乐观锁

悲观锁的话就是每次去拿数据的时候,也认为别人会修改数据,这个时候就会加上锁,这就导致其他线程想拿数据的话,就会阻塞,直到这个线程修改完成才会释放锁,让其他线程获取数据。在数据库里的行级锁、表级锁都是在操作之前就先锁住数据再操作数据 ,都属于悲观锁。Java中的 synchronized 和 ReentrantLock 等独占锁就是悲观锁思想的实现

5、线程池的原理

我之前看过线程池相关的源码,线程池主要由4个部分组成,

线程池管理器:用于创建并管理线程池

工作线程:线程池中的线程

任务接口:每个任务必须实现的接口,用于工作线程调度其运行

任务队列:用于存放待处理的任务,提供一种缓冲机制

线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线 程创建后启动这些任务,如果线程数量超过了最大数量,超出数量的线程排队等候,等其它线程执行完毕,再从队列中取出任务来执行。他的主要特点为:线程复用;控制最大并发数;管理线程。

6、线程池的核心参数都有哪些

corePoolSize(核心线程数)

(1)核心线程会一直存在,即使没有任务执行;

(2)当线程数小于核心线程数的时候,即使有空闲线程,也会一直创建线程直到达到核心线程数;

(3)设置 allowCoreThreadTimeout=true(默认 false)时,核心线程会超时关闭。

queueCapacity(任务队列容量)

(1)也叫阻塞队列,当核心线程都在运行,此时再有任务进来,会进入任务队列,排队等待线程执行。

maxPoolSize(最大线程数)

(1)线程池里允许存在的最大线程数量;

keepAliveTime(线程空闲时间)

(1)当线程空闲时间达到 keepAliveTime 时,线程会退出,直到线程数等于核心线程数

  • 20
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值