请问线程池为什么能够重复利用线程对象

调皮的芋头 2018-08-10 10:11:13
我们知道,一个线程执行完了(run方法执行完毕),就是DEAD状态,不可再次调用start,
那么线程池技术(例如ExecutorService),怎么做到一个线程对象能够重复利用呢?
...全文
565 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
galiniur0u 2018-08-17
  • 打赏
  • 举报
回复 1
线程池的实现并非是直接调用楼主所创造的哪个线程的start方法,而是借由另外一个线程来执行run。简单理解就是线程池在线程外面又包了一层壳。不断运行的是这层壳。
疯癫行者 2018-08-11
  • 打赏
  • 举报
回复
一句话解释:
就是run方法没有执行完,而是在run方法里面设置一个循环。线程没有被使用的时候处于阻塞暂停状态,需要使用的时候阻塞打开,执行任务,任务完成之后,再循环回来,再次阻塞暂停。此时仍在循环当中。所以run方法一直也没有结束,因此可以重复使用多次。
  • 打赏
  • 举报
回复
引用 2 楼 a707748808 的回复:
其实你说的也对,run方法执行完成了,线程就销毁了。所以线程池的run方法是阻塞的,以下是一段源码:
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
//看这里
while (task != null || (task = getTask()) != null) {
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 {
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 {
processWorkerExit(w, completedAbruptly);
}
}
线程销毁后没办法重新利用,只有重新创建。
 public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
*/
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
  • 打赏
  • 举报
回复
其实你说的也对,run方法执行完成了,线程就销毁了。所以线程池的run方法是阻塞的,以下是一段源码:
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
//看这里
while (task != null || (task = getTask()) != null) {
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 {
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 {
processWorkerExit(w, completedAbruptly);
}
}
wildyy 2018-08-10
  • 打赏
  • 举报
回复
线程池里的线程在执行完你给的任务后并没有结束run方法,而是进入等待状态,进入空闲队列,这些线程除非有需要销毁,否则run方法永远不会结束
verejava 2018-08-10
  • 打赏
  • 举报
回复
并发编程 之 ExecutorService 线程池 铁运行例子

http://www.verejava.com/?id=17266756343972

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧