线程是独立程序的执行路径。在java中,每个线程都扩展了java.lang.Thread类或者实现了java.lang.Runnable。
多线程是指在一个任务中同时执行两个或多个线程。在多线程中,每个任务可以有多个线程,这些线程可以并发运行,可以是异步的,也可以是同步的。您可以在我写的关于多线程的另一篇教程此处中找到有关线程和多线程的更多信息。
LinkedBlockingQueue
向队列添加和删除任务。
wait()
和 notify()
来通知等待线程新工作已经到达。以下示例显示了一个简单的工作队列,它是 Runnable
对象的队列。这是调度程序和工作队列的通用约定,尽管 Thread API 没有特别需要使用 Runnable
接口。
package tutorials; import java.util.concurrent.LinkedBlockingQueue; public class ThreadPool { private final int nThreads; private final PoolWorker[] threads; private final LinkedBlockingQueue queue; public ThreadPool(int nThreads) { this.nThreads = nThreads; queue = new LinkedBlockingQueue(); threads = new PoolWorker[nThreads]; for (int i = 0; i < nThreads; i++) { threads[i] = new PoolWorker(); threads[i].start(); } } public void execute(Runnable task) { synchronized (queue) { queue.add(task); queue.notify(); } } private class PoolWorker extends Thread { public void run() { Runnable task; while (true) { synchronized (queue) { while (queue.isEmpty()) { try { queue.wait(); } catch (InterruptedException e) { System.out.println("An error occurred while queue is waiting: " + e.getMessage()); } } task = queue.poll(); } // If we don't catch RuntimeException, // the pool could leak threads try { task.run(); } catch (RuntimeException e) { System.out.println("Thread pool is interrupted due to an issue: " + e.getMessage()); } } } } }
在处理队列时使用同步块很重要,它可以控制线程对队列的访问。
package tutorials; public class Task implements Runnable { private int num; public Task(int n) { num = n; } public void run() { System.out.println("Task " + num + " is running."); } }
import tutorials.Task; import tutorials.ThreadPool; public class Main { public static void main(String[] args) { ThreadPool pool = new ThreadPool(7); for (int i = 0; i < 5; i++) { Task task = new Task(i); pool.execute(task); } }
在上面的示例中,我们使用了 notify()
而不是 notifyAll()
。因为 notify()
比 notifyAll()
具有更理想的性能特征;特别是,notify()
会导致更少的上下文切换,这在服务器应用程序中很重要。但在其他情况下使用 notify()
时务必要确保使用 notify()
存在微妙的风险,并且仅在某些特定条件下才适合使用它。
下图演示了上面例子中的线程池设计。
图1。线程池设计
线程池是构建多线程应用程序的强大机制,但它并非没有风险。使用线程池构建的应用程序可能具有与任何其他多线程应用程序相同的并发风险,例如死锁、资源抖动、同步或并发错误、线程泄漏和请求过载。
这里有几点:
线程池对于组织服务器应用程序非常有用,正确实现它以防止任何问题(例如死锁和 wait()
或 notify()
的使用复杂性)非常重要。因此,建议考虑使用 Executor
中的 util.concurrent
类之一,例如 ThreadPoolExecutor
,而不是从头编写线程池。如果需要创建线程来处理短期任务,您可以考虑使用线程池。
这是一个线程池的教程,要下载源代码,请点击这里。
标签2: Java教程地址:https://www.cundage.com/article/jcg-implement-thread-pool-java.html