首页 > 其他分享 >线程常见面试题

线程常见面试题

时间:2023-02-21 10:13:44浏览次数:40  
标签:面试题 Thread 对象 常见 任务 线程 执行 wait

1.线程和进程有什么区别?

进程:

程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至CPU,数据加载至内存,在指令运行过程中还需要用到磁盘,网络等设备,进程就是用来加载指令,管理内存,管理IO的.

当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程.

进程就可以视为程序的一个实例,大部分程序可以同时运行多个实例进程(例如记事本,画图,浏览器等),也有的程序只能启动一个实例进程(例如网易云音乐,360安全卫士等).

线程:

一个进程之内可以分为一到多个线程.

一个线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给CPU执行.

2.并发和并行有什么区别?

并发(concurrent)是同一时间应对多件事件的能力:

单核cpu下,线程实际还是串行执行的,操作系统中有一个组件叫做任务调度器,将cpu的时间片(windows下时间片最小约为5毫秒)分给不同的程序使用,只是由于cpu在线程间(时间片很短)的切换非常快,人的感觉是同时运行的,总结为一句话就是:微观串行,宏观并行,一般会将这种线程轮流使用CPU的做法称为并发,concrrent.

并行(parallel)是同一时间动手做多件事情的能力:

多核cpu下,每个核(core)都可以调度运行线程,这时候线程可以是并行的,

3.线程创建的4中方式?

方法一:直接使用Thread

// 创建线程对象
Thread t = new Thread() {
public void run() {
// 要执行的任务
}
};
// 启动线程
t.start();

方法二:使用Runnable配合Thread

Runnable runnable = new Runnable() {
public void run(){
// 要执行的任务
}
};
// 创建线程对象
Thread t = new Thread( runnable );
// 启动线程
t.start();

方法三:FutureTask配合Thread

// 创建任务对象
FutureTask<Integer> task3 = new FutureTask<>(() -> {
log.debug("hello");
return 100;
});
// 参数1 是任务对象; 参数2 是线程名字,推荐
new Thread(task3, "t3").start();
// 主线程阻塞,同步等待 task 执行完毕的结果
Integer result = task3.get();
log.debug("结果是:{}", result);

方法四:线程池

4.线程有哪些状态?

站在JavaAPI的角度:

1.新建(NEW): new Thread();      当使用new关键字创建Thread对象,此时的线程只是一个java对象并没有和操作系统真正的线程关联;

2.可运行状态(RUNABLE): 调用start方法,当调用线程对象的start,线程对象就会和操作系统真正的线程关联,可以由CPU调度执行;

3.终结状态:run方法中代码执行完毕,当线程中的代码被cup执行完毕后,线程就处于终结状态

新建->可运行->终结是不可逆的.

4.阻塞状态:没有获取线程锁的线程,线程在执行的时候,可能多个线程抢占同一把锁。没有获取锁的线程处于阻塞状态.

当获取锁的线程释放掉锁,重新抢占锁成功->可运行状态.

5.等待状态:获取锁的线程,调用锁对象.wait方法

当其他线程调用锁对象.notify方法唤醒等待状态的线程,重新获取锁成功-->可运行状态.

6.有时限的等待:

获取锁的线程,调用锁对象.wait(long)方法,当其他线程调用锁对象.notify方法唤醒等待状态的线程,

重新获取锁成功-->可运行状态.

时间到了重新获取锁成功--->可运行状态.

调用线程sleep(long)方法:

时间到了--->可运行状态,

5.为什么要使用线程池?

1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务.

2.可以根据系统的承受能力,调整线程池中工作线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程大概需要1MB内存,线程开的越多,消耗的内存就越大,最后死机).

6.线程池的构造方法里几个参数的作用分别都是什么?

线程池就是管理线程的一个容器;在java中线程池的实现,ThreadPoolExecutor.

ThreadPoolExecutor构造方法中的7个参数.

 

 

 corePoolSize核心线程数目- 池中会保留的最多线程数;

maximumPoolSize最大线程数目 - 核心线程+急救线程的最大数目;

keepAliveTime生存时间- 救急线程的生存时间,生存时间内没有新任务,此线程资源会释放,

unit 时间单位 - 救急线程的生存时间单位(秒, 毫秒等)

workQueue -工作队列,当没有空闲核心线程时,新来的任务会加入到此队列排队,队列满会创建救急线程执行任务,当我们使用submit方法向线程池中添加一个任务;如果所有的核心线程都在执行任务;该任务就会被加入WorkQueue

threadFactory线程工厂- 可以定制线程对象的创建,例如设置线程名字,是否是守护线程等

handler拒绝策略 - 当所有线程都在繁忙,workQueue也放满时,会触发拒绝策略.

 

7.线程池流程

1.当我们向线程池中添加任务(注意线程池中不能添加线程,只能添加任务,线程池中的线程是由线程池自己管理的)

2.有核心线程执行任务:

如果核心线程都在执行任务,将任务加入到任务队列 , 等待核心线程执行完成任务后,从队列中获取任务执行, 如果队列已经满了, 创建急救线程.由救急线程执行任务, 救急线程执行完成任务后, 如果在keepAliveTime时间内没有任务执行,则销毁.  如果救急线程也无法创建, 触发拒绝策略.

8.线程池的拒绝策略有哪些?

抛异常java.util.concurrent.ThreadPoolExecutor.AbortPolicy

由调用者执行任务 java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy

丢弃任务 java.util.concurrent.ThreadPoolExecutor.DiscardPolicy

丢弃最早排队任务,把新加任务添加到工作队列 java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy

9.notify()和notifyAll()有什么区别?

notify():唤醒锁对象等待区随机一个线程,

notifyAll()唤醒锁对象等待区的所有线程.

10.wait()和sleep()的区别?

相同点:wait() ,wait(long)和sleep(long)的效果都是让当前线程暂时放弃CPU的使用权,进去WATING Time_waiting的状态.

不同点: 

方法归属不同:sleep(long) 时thread的静态方法,而wait() ,wait(long) 都是Object的成员方法,每个对象都有,

醒来时机不同: 执行sleep(long)和wait(long)的线程都会在等待相应毫秒后醒来, wait(long) 和wait() 还可以被notify唤醒,wait()如果不唤醒就一直等待下去,(其他线程调用锁对象notify,可以把这个锁上处于wait状态的一个线程唤醒) 它们都可以被打断唤醒,

锁特性不同:

wait方法必须基于锁对象调用,直接调用报错,而sleep没有限制.

wait方法执行后会释放锁资源,允许其他线程获得该对象锁.

sleep如果在synchronized代码块中执行,并不会释放对象锁.

 

标签:面试题,Thread,对象,常见,任务,线程,执行,wait
From: https://www.cnblogs.com/carney/p/17139946.html

相关文章

  • 为啥Python多线程爬虫跑的慢?
    单线程和多线程进行数据抓取结果还是大有不同的,但是要值得注意的事,如果多线程没调配好可能连单线程的效率都比不上。本次就和大家一起聊一聊单线程多线程的一些需要注意的......
  • 社招前端常考react面试题总结
    react强制刷新component.forceUpdate()一个不常用的生命周期方法,它的作用就是强制刷新官网解释如下默认情况下,当组件的state或props发生变化时,组件将重新渲染。......
  • 多线程并发(二):聊聊AQS中的共享锁实现原理
    在上一篇文章多线程并发(一)中我们通过acquire()详细地分析了AQS中的独占锁的获取流程,提到独占锁,自然少不了共享锁,所以我们这边文章就以AQS中的acquireShared()方法为例,......
  • Python多线程如何保证数据安全
    之前有一篇文章分享了有关Python多线程的一次基础语法以及GIL的相关概念,今天我们重点讲解多线程的数据安全问题。数据安全问题我们首先来举一个例子,这里定义两个函数,一个......
  • ThreadPool线程池工具类
    packagecom.rc.openapi.util;importcom.google.common.util.concurrent.ThreadFactoryBuilder;importjava.util.concurrent.*;publicclassThreadPoolService{/**......
  • 常见数学结论
    一些在OI中可能会用到的数学结论。它可能出现在算法的简化之中或者是复杂度证明之中。随时见到,随时添加。\(\sum\limits_{i=1}^n\dfrac{1}{i}=O(\lnn)+C\),\(\sum\lim......
  • 【数组与链表算法】矩阵算法在程序中常见的简单应用 | C++
    第二十三章矩阵算法:::hljs-center目录第二十三章矩阵算法●前言●矩阵算法与深度学习●一、矩阵相加●二、矩阵相乘●三、矩阵转置●四、稀疏矩阵●......
  • git常见用法
      图片来自https://www.runoob.com/git/git-basic-operations.html新建/复制git仓库:1.gitinit2.gitclone<SSH[address]>查看/创建/删除分支:gitbranch/git......
  • 【技术分享】线程本地存储(Thread Local Storage, TLS)
    开源项目:https://girakoo.com/官方文档:https://learn.microsoft.com/en-us/windows/win32/procthread/using-thread-local-storage简介线程本地存储(TLS),可以使多个线程,通......
  • 多线程频繁上下文切换
    什么是上下文切换在单核cpu中,多线程的执行是通过cpu的时间片分配,每个线程会分配到一个时间片,循环执行这些线程,线程时间片消耗完了就会进入等待状态,直到分配到新的时间......