2010-09-19 111 views
5

我对以下内容感到困惑:
要在Java程序中使用线程,最简单的方法是扩展Thread类并实现可运行接口(或简单实现可运行)。
启动线程的执行。我们必须调用Thread的start()方法,然后调用线程的run()方法。线程开始。
方法start()(除非我错了)必须精确调用,每个线程只能调用一次。因此,线程实例不能被重用,除非run方法本身以无限循环的方式运行,这有助于自定义实现线程的重用。
现在的Javadoc link text通过执行程序重新执行java线程

调用execute将重用以前构造的线程(如果可用)

我不明白这是如何实现的。 我在执行方法的执行方法中提供了我的自定义线程,例如

ExecutorService myCachedPool = Executors.newCachedThreadPool(); 
    myCachedPool.execute(new Runnable(){public void run(){ 
    //do something time consuming 

    }}); 

如何将此自定义线程删除到执行程序框架被重用?
Executor被允许调用方法start()超过1次,而我们不能在我们的程序中? 我误解了什么吗?

谢谢。

回答

4

请注意,它不是Executor,它调用start() - 它是ExecutorService。不,它不会拨打start()两次。它不会启动直接使用Thread.start() ...的任务,而是启动一个知道该线程池工作队列的线程。线程将基本上等待,直到有一些工作要做,然后将其提取并执行,然后再返回到等待状态。所以虽然线程执行多个任务,但是Thread.start()只被调用一次。

编辑:通过评论来判断,你对Runnable(这是一个要执行的任务)和Thread(这是执行任务)之间的区别有点困惑。

相同的线程可以执行多个任务。对于不使用线程池一个很简单的例子,考虑一下:

(忽略使用List<T>从多个线程的潜在线程安全的问题。)

您可以创建一个一大堆Runnable任务能够做不同的事情,然后创建一个MultiRunnable来轮流运行它们。将MultiRunnable的实例传递给Thread构造函数,然后在启动线程时,它将执行每个原始可运行任务。这有帮助吗?

+0

@乔恩:对不起,我失去了你。所以框架的内部线程被重用,而不是作为参数传递的可运行?我委托给框架的线程每次都会重新实例化,但是由框架创建的内部线程的同一个实例进行重新实例化? – Cratylus 2010-09-19 11:50:00

+0

@ user384706:是的。你的runnable *不是一个线程 - 它只是一个要执行的任务。你需要区分两者;他们非常不同。 – 2010-09-19 11:53:27

+0

@Jon:非常感谢。我唯一不确定的是,使用Executors.newCachedThreadPool()的好处是什么? 因为如果我实现runnable(对于任务)的类实例化的代价很高,那么它将不会被重用,并且框架的相同线程将继续使用任务的新实例。那么我会从这个api中获得什么?除非这个概念是每个实现可运行的类都是最小的。 – Cratylus 2010-09-19 12:05:01

5

它不是多次调用start();相反,池中的线程永远不会完成,但只是保持活着 - 等待。如果您想查看它,可以下载源代码。

线程池中的每个线程都可以简单地使用wait()为Executor递交一个新的Runnable,但线程自己的run()方法尚未完成。它只是等待给Executor一个新的Runnable。

+0

所以你的意思是说,在javadoc它说“以前构建的线程将被重用”它不是指我运行的执行,但执行者框架的内部线程的runnable?所以我的Runnable将被同一个线程池重新实例化?我明白你在说什么吗? – Cratylus 2010-09-19 11:47:35

+2

您的Runnable将不会被重新使用。您的Runnable实例将被赋予池中的其中一个线程。该线程有它自己的'run()'方法,它不是(不能)被你的Runnable的'run()'方法取代。 Thread的run()方法会调用你的'Runnable'的'run()'方法,然后在你的'Runnable.run()'完成后,线程将最终(有一些簿记必须完成)去回到'等待'。 – jbindel 2010-09-19 14:37:27

1

要多次“启动”一个线程,请创建一个可运行的程序。例如:

//NO 
private class T extends Thread { //not necessary to implement runnable 
    public void run(){ 
     //... 
    } 
} 
void someMethod(){ 
    T a = new T(); 
    a.start(); 
    a.start(); //NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO 
} 

相反,

//Yes 
private class T implements Runnable { 
    public void run(){ 
     //... 
    } 
} 
void someMethod(){ 
    T a = new T(); 
    new Thread(a).start(); 
    new Thread(a).start(); //YES YES YES 
} 

也可以做到这一点:

void someMethod(){ 
    final Runnable r = new Runnable(){ 
     public void run(){ 
      //... 
     } 
    }; 
    new Thread(r).start(); 
    new Thread(r).start(); 
} 
// r could also be a field of you class.