多线程线程池的实现java
线程是独立程序的执行路径。 在java中,每个线程都扩展java.lang.Thread类或实现java.lang.Runnable。
多线程是指在一个任务中同时执行两个或多个线程。在多线程中,每个任务可以有多个线程,并且这些线程可以异步或同步地并行运行。 您可以在我在此处撰写的另一篇有关多线程的教程中找到有关线程和多线程的更多信息。
1.什么是线程池
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 threadstry {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()
它是唯一适当使用它在特定条件下。
下图演示了以上示例中的线程池设计。
2.有效使用线程池
线程池是一种用于构造多线程应用程序的强大机制,但并非没有风险。 使用线程池构建的应用程序可能具有与任何其他多线程应用程序相同的并发风险,例如死锁 , 资源崩溃,同步或并发错误,线程泄漏和请求重载 。
这里有几点:
- 不要将同步等待其他任务的任务排入队列,因为这会导致死锁。
- 如果任务需要等待诸如I / O之类的资源,请指定最大等待时间,然后使任务执行失败或重新排队。 这保证了通过释放线程执行可能成功完成的另一任务将取得一些进展。
- 有效地调整线程池的大小,并了解线程太少或线程太多都会导致问题。 线程池的最佳大小取决于可用处理器的数量以及工作队列上任务的性质。
3.结论
线程池对于组织服务器应用程序很有用,并且正确地实现它以防止任何问题(例如死锁和wait()
或notify()
使用的复杂性)非常重要。 因此,建议考虑使用util.concurrent
中的Executor
类之一,例如ThreadPoolExecutor
,而不是从头开始编写线程池。 如果要求创建线程来处理短期任务,则可以考虑使用线程池。
4.下载源代码
这是线程池的教程,要下载源代码,请单击此处 。
翻译自: https://www.javacodegeeks.com/2016/12/implement-thread-pool-java.html
多线程线程池的实现java