5

我需要询问线程池是如何实现的,以便每次发生任务提交时都有恒定数量的线程执行。(在Executor中避免每次线程创建和删除的开销)

executor.submit(Runnable)

假设我们在开始时创建了一些线程,当任务到来时,我们使用任何 Queue impl 将任务分配给它们(线程)。但是在完成它的任务之后,当按照线程的生命周期说,一个线程如何再次返回到它的池中?

“执行其运行方法后,它进入 TERMINATED 状态,不能再次使用”

我不明白线程池是如何工作的,因为它有恒定数量的线程来执行其队列中的任何任务。

如果有人可以在任务完成后向我提供线程重用的示例,那就太好了。

!!提前致谢 。!!

4

5 回答 5

3

“执行其运行方法后,它进入 TERMINATED 状态,不能再次使用”

它没有完成它run()相反它有一个循环来运行你提供的任务的 run()。


显着简化线程池模式,您将拥有如下所示的代码。

final BlockingQueue<Runnable> tasks = new LinkedBlockingQueue<Runnable>();

public void submit(Runnable runs) {
    tasks.add(runs);
}

volatile boolean running = true;

// running in each thread in the pool
class RunsRunnable implement Runnable {
    public void run() {
        while(running) {
           Runnable runs = tasks.take();
           try {
              runs.run();
           } catch(Throwable t) {
              // handles t
           }
        }
    }
 }

在此示例中,您可以看到当每个任务的 run() 完成时,线程本身的 run() 直到池关闭时才完成。

于 2012-10-06T12:30:19.410 回答
1

通常当我们使用线程池时会发生什么,它在 Run 方法中被强制迭代运行。直到队列中有可用的任务。

在下面的示例中 pool.removeFromQueue() 将迭代运行。

public class MyThread<V> extends Thread {
    private MyThreadPool<V> pool;
    private boolean active = true;

    public boolean isActive() {
        return active;
    }

    public void setPool(MyThreadPool<V> p) {
        pool = p;
    }

    /**
     * Checks if there are any unfinished tasks left. if there are , then runs
     * the task and call back with output on resultListner Waits if there are no
     * tasks available to run If shutDown is called on MyThreadPool, all waiting
     * threads will exit and all running threads will exit after finishing the
     * task
     */
    @Override
    public void run() {
        ResultListener<V> result = pool.getResultListener();
        Callable<V> task;
        while (true) {
            task = pool.removeFromQueue();
            if (task != null) {
                try {
                    V output = task.call();
                    result.finish(output);
                } catch (Exception e) {
                    result.error(e);
                }
            } else {
                if (!isActive())
                    break;
                else {
                    synchronized (pool.getWaitLock()) {
                        try {
                            pool.getWaitLock().wait();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    void shutdown() {
        active = false;
    }

需要设计你的线程池

public MyThreadPool(int size, ResultListener<V> myResultListener) {
        tasks = new LinkedList<Callable<V>>();
        threads = new LinkedList<MyThread<V>>();
        shutDown = false;
        resultListener = myResultListener;
        for (int i = 0; i < size; i++) {
            MyThread<V> myThread = new MyThread<V>();
            myThread.setPool(this);
            threads.add(myThread);
            myThread.start();
        }
    }
于 2016-03-08T13:40:42.377 回答
0

您可以在这里查看:http ://www.ibm.com/developerworks/library/j-jtp0730/index.html以获取更多详细信息和实现示例。如果队列为空,池中的线程将等待,并且一旦收到队列有一些元素的通知,每个线程都会启动 consome 消息。

于 2012-10-06T12:31:11.167 回答
0

ExecutorService executor = Executors.newFixedThreadPool(2);

-上述语句创建了一个固定大小为 2 的 ThreadPool。

executor.execute(new Worker());

-上面的语句采用了实现Runnable接口的类 Worker 的实例。

-现在这里Executors是一个中间对象,执行任务。它管理线程对象。

-通过执行上述语句,该run()方法将被执行,一旦run()方法完成,线程不会进入死状态而是移回池中,等待分配另一个工作,因此它可以再次移动进入 Runnable 状态然后运行,这一切都由 Executors 处理。

executor.shutdown();

-上面的语句将关闭 Executors 本身,优雅地处理由它管理的所有线程的关闭..shutdown()在该中心对象上,这反过来可以终止每个注册的 executors。

////////// Edited Part//////////////////////

-首先Runnable有一个run()方法不能返回任何东西,而run()方法不能抛出检查异常,所以Java 5中引入了Callable,它是Parametric类型的,有一个方法叫call(),它能够返回和抛出 Checked 异常。

现在看这个例子:

Thread t = new Thread(new Worker());

t.run();

t.start();

- t.run()只是对run()方法的简单调用,这不会跨越thread of execution.

-while t.start()为 的 的重要的事情做准备initializationthread of execution然后调用run()方法Runnable,然后将 分配新形成Task的,然后快速返回.... thread of execution

Swing使用和时,Java 中的线程成为必需品AWT主要是 GUI 组件

于 2012-10-06T12:50:33.543 回答
0

我完全同意彼得的观点,但想添加与 ExecutorService 执行流程相关的步骤,以便清楚地理解。

  • 如果您创建线程池(固定大小的池),则并不意味着创建了线程。
  • 如果您提交和/或执行新任务(RunnubleCallable)新线程将被创建 JUTS 如果创建的线程计数<池大小
  • 创建的线程不返回池,线程可以等待阻塞队列中的新值,此时我们可以调用 RETURNING TO POOL
  • 来自上述 Peter 等池执行人员的所有线程。
于 2012-10-06T14:30:53.370 回答