当前位置:网站首页>Interview, about thread pool
Interview, about thread pool
2022-07-02 18:09:00 【A Jian Dong a little】
background
I've been interviewing for a job recently , The interviewer asked a lot about thread pool . But I found that most interviewers can't ask anything , Metropolis asked which core parameters , Pull it by yourself 12345 Parameters , And then it didn't and then ( That's the next question ). But it doesn't rule out that some interviewers can , Will aim at your understanding , Ask you some slightly source code level or design some scenarios for you to answer ( Personally, I prefer this ).
Core parameters
- corePoolSize Number of core threads
- maximumPoolSize Maximum number of threads
- keepAliveTime Thread idle time
- workQueue Task buffer queue
- RejectedExecutionHandler Refusal strategy , Exception thrown by default ( Others include discarding old tasks in the queue 、 Discard the current task 、 Use the current thread to execute the task )
It's worth thinking about
- keepAliveTime What's the use of parameters , Where is it reflected ?
- corePoolSize Threads created within the number of core threads will be recycled ?
- We know that when a worker thread (worker) A number greater than or equal to corePoolSize And after the cache queue is full , Will be based on maximumPoolSize Judge , If it is less than , Then start a thread to execute our task . Is there any way not to abandon any tasks , You don't need the current thread to execute ?
- Why? Worker Inheritance AbstractQueuedSynchronizer, Where does it work ?
- shutdown() and shutdownNow() What's the difference ?
Think of some things in life
The boss of an outsourcing company recently received a small project , project manager ( call A) Sort out the needs , Dismantling task , Report to the boss conservatively 10 Developers . Um. , Hire people immediately without saying a word , work . One day , Party A puts forward new requirements ,A Pinch fingers , There are a lot of tasks , The current development is still busy , I can't arrange , Ah , First disassemble the task and save it Requirement Library hold . Sure enough, it's Party A's father , A few days later , Put forward new requirements ,A I can't help scolding mmp 了 , Because the demand pool is full , Only report to the boss , The boss touched his head , Currently, developers are still I can accept ( ceiling 20 Individual development ) Within the scope of , Hire people immediately without saying a word , work . here , Boss and A Ink stains , If we continue to raise new demands , There are more developers than I can accept , Talk to them directly Showdown hold .
In fact, the boss also has his own need to think carefully , recruit 20 Individual development , It's not a long-term plan ( Programmers are always 2w start ), When the project requirements are completed , Just leave a few cores , cut away I didn't live for a few days Dry .
The above bold text , It can barely match the core parameters of the thread pool ( Take your seats by yourselves ), so what , Answer the previous questions about this story
Back to the previous question
- keepAliveTime: It is mainly used to recycle those idle threads , After the thread is created , Finish the task , Immediately go to the queue to get the task , If there is no task within the specified time ( That is, every developer finishes the task at hand , You have to go to the demand library to get the task , Keep repeating this operation ), The thread will be recycled . Of course , This has certain conditions , such as : Allow the number of core threads to timeout or the number of worker threads is greater than the configured number of core threads .
- corePoolSize: The threads created within the number of core threads are the same as those created later , There are no so-called fixed core threads in the thread pool . Each thread completes the task , Then pull a task out of the queue to continue execution , When there is no task , If the thread cannot receive it, it will be recycled ( That's your 10 Employees start first , It doesn't mean you can work in the company forever , If later employees can work more actively than you , I still drive you away ).
- Here we mainly study the rejection strategy . We can customize a rejection policy and continue to put our tasks into the thread pool , such as : Create a new queue to store the tasks that trigger the rejection policy , Open another thread to take tasks out of the queue and throw them back into the thread pool .
- There are two places , Need to use worker To lock . Namely runWorker() and shutdown() function . Personal understanding is execution runWorker Function time , If you lock the task when you get it , The author does not want to execute shutdown( It mainly marks the interrupt of the working thread ) And have any impact on the task that the thread is executing ( Although the thread is marked with an interrupt , It will not have an absolute impact on threads , It mainly depends on how developers deal with , This can be seen in detail interrupt Related knowledge ).
- perform shutdown(), The thread pool state will be changed to SHUTDOWN, And mark the worker thread with an interrupt , No new tasks will be received at this time , but , If the queue has tasks , be , It will continue . perform shutdown(), The corresponding state of the thread pool is STOP, And force all worker threads to be marked with interrupt , here , Also won't accept new tasks , If there are tasks in the queue , Will remove the task , Not execute . On the whole , These two functions have no effect on the task being performed ( It is excluded here that you have done other processing for the interrupt exception ).
For the above problems , Let's take a look at the source code :
Thread execution logic :
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
// Get the task , Get in while Logic , otherwise , Deal with the logic of recycling later
// It can be seen from here that , There is no so-called fixed core thread , All by robbing , Grab it and continue , Destroy if you can't get it
while (task != null || (task = getTask()) != null) {
// Get task , Lock
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
// Here is our specific business logic
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
// Process recycle thread logic
processWorkerExit(w, completedAbruptly);
}
}Get the task logic in the queue :
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
int wc = workerCountOf(c);
//(1) allowCoreThreadTimeOut The default is false
// It mainly depends on wc > corePoolSize;
// Are workers subject to culling?
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
//(3) According to reason , If there is no task added at this time , This condition is satisfied , It will eventually arrive at return null return , End infinite traversal
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
//(2) When timed by true, And at the appointed time keepAliveTime If the task is not found, it will return a individual null
// Because in for(;;) Inside , Will continue to traverse back to (3) It's about
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}shutdown Logic , The processing thread pool status is SHUTDOWN, Traverse worker threads , And then get the lock , If it succeeds, mark it with interruption
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers) {
Thread t = w.thread;
// Here is also an attempt to get worker Lock of , This means that if the thread is executing a task ,
// That will block here , That is, you can't mark
if (!t.isInterrupted() && w.tryLock()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}shutdownNow Logic , The processing thread pool status is STOP. Traverse worker threads , Mark the thread with an interrupt . Remove tasks from the queue , And back to .
void interruptIfStarted() {
Thread t;
// Here with shutdown Dissimilarity ,, A little mandatory
// because getState() >= 0 Can basically satisfy , Although the thread is already executing the task
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
}
private List<Runnable> drainQueue() {
BlockingQueue<Runnable> q = workQueue;
ArrayList<Runnable> taskList = new ArrayList<Runnable>();
// Remove elements from queue
q.drainTo(taskList);
if (!q.isEmpty()) {
// here , It is mainly to reconfirm whether there are elements in the queue , Make sure no one is left alive .
// Because it is possible that q.drainTo(taskList) period , User threads continue to drop tasks into the thread pool .
for (Runnable r : q.toArray(new Runnable[0])) {
if (q.remove(r))
taskList.add(r);
}
}
return taskList;
}Wrote last
Thread pool no matter in daily work or interview , The frequency of occurrence is still relatively high . If you pay attention to accumulation at ordinary times , When in use, it can be handy . in addition , The above is only my preliminary understanding of thread pool , If there is something wrong , Welcome to point out .
边栏推荐
- Mysql - opérations de base de la base de données
- Yilong em78p153k dip14 MCU
- 应广单片机(MCU单片机科普)
- Yingguang single chip microcomputer development specification pmc131 with AD chip to detect battery voltage single chip microcomputer sop8/14
- WPS inserts a picture and displays it completely
- Development and application case of pms134 scheme of Yingguang single chip microcomputer with original packaging
- 切换变换的时候记得使用三元表达式
- 515. Find the maximum value in each tree row
- 1288_ Implementation analysis of vtask resume() interface and interrupt Security version interface in FreeRTOS
- Typescript
猜你喜欢

Wechat nucleic acid detection and appointment applet system graduation design (3) background function

Taiwan Feiling fm8pb513b MCU provides MCU program development product design

MySQL advanced - transaction and index

My creation anniversary

Customize a loading instruction

微信小程序视频分享平台系统毕业设计毕设(7)中期检查报告

Picking up the camera is the best artistic healing

Editor编辑器扩展在Scene View添加按钮和logo

Outsourcing for five years, abandoned

win10 kms activator
随机推荐
D constructor problem
PHP gets the number of days, hours, minutes and seconds between the two timestamps
Deep understanding of ThreadLocal
Editor Editor Extension add button and logo in scene view
把xshell连接服务器关掉,运行的jar包就自动停止的解决方案
Wechat nucleic acid detection appointment applet system graduation design completion (4) opening report
wps插入图片后使图片完整显示
好玩的免费GM游戏整理汇总
977. Square of ordered array
微信小程序视频分享平台系统毕业设计毕设(7)中期检查报告
详解Kubernetes网络模型
【Golang | gRPC】使用openssl生成证书
应广单片机开发调试应注意的问题
好评率计算
微信小程序视频分享平台系统毕业设计毕设(6)开题答辩PPT
Taiwan Feiling fm8pb513b MCU provides MCU program development product design
wait_for_gap -- 从主库归档备库恢复归档
人人工势场法
应广单片机开发案例
使用NPOI导出Excel文件