线程池实现

A thread is an independent program’s path of execution. In java, each thread extends the java.lang.Thread class or implements java.lang.Runnable.

Multithreading refers to the execution of two or more threads concurrently within a single task.In multithreading, each task can have many threads, and these threads can run concurrently, either asynchronously or synchronously. You can find more information about thread and multithreading in another tutorial that I wrote about multithreading here.

1. What is Thread pool

Thread pool represents a group of worker threads which execute tasks, each thread can be reused many times. If a new task is submitted when all threads are active, they will wait in the queue until a thread is available. Thread pool implementation internally uses  LinkedBlockingQueue for adding and removing tasks to the queue.
What we usually want is a work queue combined with a fixed group of worker threads, which uses  wait()and  notify() to signal waiting threads that new work has arrived. The following example shows a simple work queue which is queue of  Runnable objects. This is a common convention for schedulers and work queues, although there is no particular need imposed by the Thread API to use the  Runnable interface.
01 packagetutorials;
02  
03 importjava.util.concurrent.LinkedBlockingQueue;
04  
05 publicclass ThreadPool {
06     privatefinal int nThreads;
07     privatefinal PoolWorker[] threads;
08     privatefinal LinkedBlockingQueue queue;
09  
10     publicThreadPool(intnThreads) {
11         this.nThreads = nThreads;
12         queue = newLinkedBlockingQueue();
13         threads = newPoolWorker[nThreads];
14  
15         for(inti = 0; i < nThreads; i++) {
16             threads[i] = newPoolWorker();
17             threads[i].start();
18         }
19     }
20  
21     publicvoid execute(Runnable task) {
22         synchronized(queue) {
23             queue.add(task);
24             queue.notify();
25         }
26     }
27  
28     privateclass PoolWorker extendsThread {
29         publicvoid run() {
30             Runnable task;
31  
32             while(true) {
33                 synchronized(queue) {
34                     while(queue.isEmpty()) {
35                         try{
36                             queue.wait();
37                         }catch(InterruptedException e) {
38                             System.out.println("An error occurred while queue is waiting: " + e.getMessage());
39                         }
40                     }
41                     task = queue.poll();
42                 }
43  
44                 // If we don't catch RuntimeException,
45                 // the pool could leak threads
46                 try{
47                     task.run();
48                 }catch(RuntimeException e) {
49                     System.out.println("Thread pool is interrupted due to an issue: " + e.getMessage());
50                 }
51             }
52         }
53     }
54 }

It is important to use synchronise block while working with the queue, to control the access of threads to the queue.

01 package tutorials;
02  
03 public class Task implements Runnable {
04  
05     private int num;
06  
07     public Task(int n) {
08         num = n;
09     }
10  
11     public void run() {
12         System.out.println("Task " + num + " is running.");
13     }
14 }
01 import tutorials.Task;
02 import tutorials.ThreadPool;
03  
04 public class Main {
05  
06     public static void main(String[] args) {
07         ThreadPool pool = new ThreadPool(7);
08  
09         for (int i = 0; i < 5; i++) {
10             Task task = new Task(i);
11             pool.execute(task);
12         }
13 }

In the above example, we used notify() instead of notifyAll(). Because notify() has more desirable performance characteristics than notifyAll(); in particular, notify() causes many fewer context switches, which is important in a server application. But it is important to make sure when using notify() in other situation as there are subtle risks associated with using notify(), and it is only appropriate to use it under certain specific conditions.

The following figure demonstrates the thread pool design in the above example.

Figure1. Thread pool design

2. Effective use of thread pools

Thread pool is a powerful mechanism for structuring multithreaded applications, but it is not without risk. Applications built with thread pools could have all the same concurrency risks as any other multithreaded applications, such as deadlockresource thrashing, synchronization or concurrency errors, thread leakage and request overload.

Here are some points:

  • Do not queue tasks which wait synchronously for other tasks as this can cause a deadlock.
  • If the task requires to wait for a resource such as I/O, specify a maximum wait time and then fail or requeue the task execution. This guarantees that some progress will be made by freeing the thread for another task that might complete successfully.
  • Tune the thread pool size effectively, and understand that having too few threads or too many threads both can cause problems. The optimum size of a thread pool depends on the number of available processors and the nature of the tasks on the work queue.

3. Conclusion

The thread pool is useful for organizing server applications and it is really important to implement it properly to prevent any issues such as deadlock and complexity of usage for wait() or notify(). So, it is recommended to consider using one of the Executor classes from util.concurrent, such as ThreadPoolExecutor, rather than writing thread pool from scratch. If the requirement is to create threads to handle short-lived tasks, you could consider using a thread pool instead.

4. Download the Source Code

This was a tutorial for thread pool, to download the source code, click here.


转自:https://www.javacodegeeks.com/2016/12/implement-thread-pool-java.html


其它相关文章http://blog.csdn.net/w2393040183/article/details/52177572

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值