我知道不应该调用run方法来启动新的线程执行,但是我引用了this article,他们在另一个run方法中调用了runnable.run();
,这似乎意味着它开始了一个新线程或者它根本不是 创建 线程,它只是创建一个新线程并在同一个线程中运行所有runnable,即按任务执行任务?
这是文章引用的代码。
public class ThreadPool {
private BlockingQueue taskQueue = null;
private List<PoolThread> threads = new ArrayList<PoolThread>();
private boolean isStopped = false;
public ThreadPool(int noOfThreads, int maxNoOfTasks){
taskQueue = new BlockingQueue(maxNoOfTasks);
for(int i=0; i<noOfThreads; i++){
threads.add(new PoolThread(taskQueue));
}
for(PoolThread thread : threads){
thread.start();
}
}
public synchronized void execute(Runnable task) throws Exception{
if(this.isStopped) throw
new IllegalStateException("ThreadPool is stopped");
this.taskQueue.enqueue(task);
}
public synchronized void stop(){
this.isStopped = true;
for(PoolThread thread : threads){
thread.doStop();
}
}
}
和
public class PoolThread extends Thread {
private BlockingQueue taskQueue = null;
private boolean isStopped = false;
public PoolThread(BlockingQueue queue){
taskQueue = queue;
}
public void run(){
while(!isStopped()){
try{
Runnable runnable = (Runnable) taskQueue.dequeue();
runnable.run();
} catch(Exception e){
//log or otherwise report exception,
//but keep pool thread alive.
}
}
}
public synchronized void doStop(){
isStopped = true;
this.interrupt(); //break pool thread out of dequeue() call.
}
public synchronized boolean isStopped(){
return isStopped;
}
}
的问题:
为什么在构造函数中调用 thread.start(); ?
如果在之前调用 thread.start(); ,我该如何识别我的任务 调用 this.taskQueue.enqueue(task);
要了解所有这些,请为此示例发布一个驱动程序类 maxNoOfTasks = 10 和 noOfThreads = 3 。输出 我将非常感激。
感谢
答案 0 :(得分:10)
我在引用这篇文章的时候称他们为
runnable.run()
;在另一个run方法中,它似乎意味着它启动了一个新线程。
看一下代码,我根本没有看到这个含义。
它没有开始新线程。它从当前池线程的队列中运行下一个Runnable
。
我知道不应该调用run方法来启动新的线程执行...
不不应该,不能。 :-)在当前线程上调用run
只调用run
,就像任何其他方法调用一样。
- 为什么在构造函数中调用
醇>thread.start();
?
启动刚刚使用new PoolThread(taskQueue)
创建的主题。
- 如果在调用
之前调用thread.start();
this.taskQueue.enqueue(task);
,我该如何处理我的任务? 醇>
您将其传递给execute
。它被添加到要做的事情的队列中(taskQueue
)。 PoolThread
创建的ThreadPool
之一会在下一次免费时将其提取。
- 要理解所有这些,请为此示例发布一个驱动程序类,其中包含maxNoOfTasks = 10和noOfThreads = 3.并且非常感谢输出。
醇>
我不知道司机班的意思,但我认为回答问题就足够了。
- 运行方法中的
醇>Runnable.run()
是否会启动一个新线程?
没有
所以要了解它的作用,请说你创建一个包含5个线程的ThreadPool
。 ThreadPool
构造函数立即创建并启动五个PoolThread
个线程。那些线程经常检查taskQueue
以查看是否有任何事情要做,如果有,他们会这样做。
当然,最初,taskQueue
始终为空,因此线程正忙着等待,不断地在taskQueue
中检查某些内容。 (这不是非常理想的,它没有任何理由燃烧CPU。最好在没有任何事情的情况下暂停线程,但这已经开始远离实际的问题了。)
然后,在某些时候,您调用execute
并传递任务。这会将其添加到taskQueue
。下一次五个线程中的一个检查taskQueue
中的某个内容时,它会找到它,然后在该线程上运行 (而不是新线程)。
答案 1 :(得分:3)
<强> 4。 Run方法中的Runnable.run()是否会启动一个新线程?
不,它不会启动新线程,不能通过调用run()方法启动新线程,因为在调用start方法之前JVM不会创建新线程。
如果直接调用run()方法,则会在同一个线程上调用它。 JVM不会创建单独的线程来执行,它将在同一个线程上执行。
在任何线程实例上,如果你调用start()方法,它将创建一个新线程,但是如果你在同一个实例上第二次调用start()方法,它将抛出java.lang.IllegalStateException,因为该线程已经启动并且你不能再重新启动它。
您只能在Java中暂停一个线程。一旦它死了它就消失了。
我认为这可能是这样打电话的理由。
Runnable runnable = (Runnable) taskQueue.dequeue();
runnable.run();
答案 2 :(得分:2)
为什么要thread.start();在构造函数中调用?
启动池构造函数中的线程。
线程已经在运行。
Runnable runnable = (Runnable) taskQueue.dequeue();
阻止正在运行的线程
taskQueue.enque()将类型为Runnable的新对象放入队列,任何被阻塞的线程都会获取此Runnable并执行它。创建池时会启动所有线程,并且这些线程只是简单执行Runnable。