通过执行程序的java线程重用

时间:2010-09-19 10:48:12

标签: java multithreading threadpool executorservice executors

我对以下内容感到困惑:
要在Java程序中使用线程,最简单的方法是扩展Thread类并实现runnable接口(或简单地实现runnable)。
启动线程的执行。我们必须调用Thread的方法start(),然后调用线程的方法run()。所以线程开始了。
方法start()(除非我错了)必须为每个线程准确调用。因此,除非以某种方式运行方法本身在无限循环中运行,以便于自定义实现线程的重用,否则不能重用线程实例。
现在是javadoc link text  说

  

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

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

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

  }});

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

谢谢。

3 个答案:

答案 0 :(得分:5)

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

线程池中的每个线程只需wait(),Executor就可以将新的Runnable交给它,但Thread自己的run()方法尚未完成。它只是等待一个新的Runnable被提供给Executor。

答案 1 :(得分:4)

请注意,调用Executor的{​​{1}}不是start() - ExecutorService。不,它不会两次调用start()。它不会启动您使用Thread.start()直接提供的任务...而是启动一个知道该线程池的工作队列的线程。线程基本上会等到有一些工作要做,然后拿起并执行它,然后再回到等待状态。因此,虽然线程执行多个任务,但Thread.start()仅被调用一次。

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

同一个线程可以执行多个任务。有关不使用线程池的非常简单的示例,请考虑以下事项:

public class MultiRunnable implements Runnable
{
    private final List<Runnable> runnables;

    public MultiRunnable(List<Runnable> runnables)
    {
        this.runnables = runnables;
    }

    public void run()
    {
        for (Runnable runnable : runnables)
        {
             runnable.run();
        }
    }
}

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

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

答案 2 :(得分:1)

要多次“启动”一个线程,请创建一个runnable。例如:

//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.