`
xly_971223
  • 浏览: 1283591 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

线程池的实现

阅读更多
线程池也许很多比较陌生 但是提到servlet每个人都知道,servlet就是用线程池来处理请求的
一个线程池由线程池管理器 工作线程 任务队列和任务接口组成
一 线程池管理器---ThreadPoolMananger 主要负责启动 停止工作线程
public class ThreadPoolManager {

	private static int DEFAULT_POOL_SIZE = 4;
	private List<WorkThread> threadPool;
	private Queue<Task> taskQueue;
	private int poolSize;
	
	public ThreadPoolManager(){
		this(DEFAULT_POOL_SIZE);
	}
	
	public ThreadPoolManager(int poolSize){
		if(poolSize <= 0){
			this.poolSize = DEFAULT_POOL_SIZE;
		}else{
			this.poolSize = poolSize;
		}
		
		threadPool = new ArrayList<WorkThread>(this.poolSize);
		taskQueue = new ConcurrentLinkedQueue<Task>();
		
		startup();
	}
	
	/**
	 * 启动线程池 开始处理任务
	 */
	private void startup(){
		System.out.println("启动工作线程。。。");
		synchronized(taskQueue){
			for(int i = 0; i < DEFAULT_POOL_SIZE; i++){
				WorkThread workThread = new WorkThread(taskQueue);
				threadPool.add( workThread );
				workThread.start();
			}
		}
		
	}
	
	/**
	 * 停止工作线程。工作线程不一定立即停止,只有在线程处于运行状态时会立即停止
	 */
	public void shutdown(){
		System.out.println("停止工作线程.");
		synchronized(taskQueue){
			for(int i = 0; i < DEFAULT_POOL_SIZE; i++){
				threadPool.get(i).shutdown();
			}
		}
	}
	
	/**
	 * 添加消息到队尾,  
	 */
	public void addTask(Task task){
		synchronized(taskQueue){
			taskQueue.add(task);
			taskQueue.notifyAll();  
		}
	}

}


二 工作线程---WorkerThread 顾名思义 它本身就是一个线程,而且是专门用来工作的,工作线程的主要任务是从任务队列中取出任务 然后执行任务
/**
 * 工作线程
 * @author XuLiangYong
 * Jul 20, 2007 3:47:52 PM
 */
public class WorkThread extends Thread{
	private boolean shutdown = false;
	private Queue<Task> queue;
	
	public WorkThread(Queue<Task> queue){
		this.queue = queue;
	}
	
	public void run(){
		while(!shutdown){
			synchronized(queue){ //获得对象锁 禁止其他线程访问
				if(!queue.isEmpty()){
					//处理任务 
					Task task = queue.poll();
					task.execute();
				}else{
					try {
						queue.wait(); //释放锁 线程处于阻赛状态 等待notify唤醒
					} catch (InterruptedException e) {
					}
				}
			}
		}//end while
	}
	
	/**
	 * 调用该方法后不一定会立即结束线程, 只有在线程处于运行状态且处理完当前任务后才结束
	 */
	public void shutdown(){
		shutdown = true;
	}
}


三 任务队列---TaskQueue FIFO数据结构 在出对入队的时候要锁定对象避免两个线程重复处理某任务
在这里我采用的是java提供的ConcurrentLinkedQueue队列,这是一个用链表实现的队 可无限的扩大,具体用法请看doc
用到队列的地方主要有两个 addTask(Task task) 和 Task task = queue.poll();

四 任务接口---Task 任务接口只有一个方法 execute(),使用者只需实现这个接口就可以了
public interface Task {
	void execute();
}


用法:
public class TestThreadPoolManager extends TestCase {
	
	public void test(){
		ThreadPoolManager pool = new ThreadPoolManager();
		for(int i = 0; i < 100; i++){
			pool.addTask(new SimpleTask(new MyManager(), i)); //SimpleTask实现了Task接口
		}
		pool.shutdown();
	}
	
}

可以看出用户的使用非常简单 
在jdk5中 java提供了线程池 有时间再写一个jdk5的线程池的例子
有一点注意 千万不要在servlet中调用线程池  因为servlet本来就是一个线程池
分享到:
评论
4 楼 kyoo_1985 2015-04-16  
WorkThread的run方法感觉有点问题,如果不为空就取出来Task进行执行,如果Task执行很长时间,这个时候其他线程其实是永远得不到执行的,因为其他线程永远获取不到queue这个锁。
这里应该把task.execute放到synchronized外面去吧。

public void run(){  
        while(!shutdown){  
            synchronized(queue){ //获得对象锁 禁止其他线程访问  
                if(!queue.isEmpty()){  
                    //处理任务   
                    Task task = queue.poll();  
                    task.execute();  
                }else{  
                    try {  
                        queue.wait(); //释放锁 线程处于阻赛状态 等待notify唤醒  
                    } catch (InterruptedException e) {  
                    }  
                }  
            }  
        }//end while  
    }  


改为
public void run() {
        while (!shutdown) {
            ITask task = null;
            synchronized (this.taskQueue) {
                if (!taskQueue.isEmpty()) {
                    task = taskQueue.poll();

                } else {
                    try {
                        taskQueue.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            // synchronized外面
            if (task != null) {
                task.execute();
            }

        }
    }
3 楼 yxrs123456 2012-08-25  
最近在了解线程池的实现,谢谢分享精神;
贴上自己的测试结果,SimpleTask实现:
package com.me.test.threadpool.xly;
/**
 * 
 * <br/> 上午11:01:10 2012-8-25
 * @Author <a href="mailto:mestudying@sina.com">Junwei Zhang</a><br/>
 **/
public class SimpleTask implements Task {
	
	private int taskID = 0;

	public SimpleTask(int id) {
		this.taskID = id;
	}

	@Override
	public void execute() {
		try {
			// 模拟任务执行
			System.out.println("-----"+ Thread.currentThread().getName() +"---execute--SimpleTask[" + this.taskID + "] Begin...");
			Thread.sleep(1000);
			System.out.println("-----"+ Thread.currentThread().getName() +"---execute--SimpleTask[" + this.taskID + "] End...");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

TestThreadPoolManager实现:
package com.me.test.threadpool.xly;

import junit.framework.TestCase;


public class TestThreadPoolManager extends TestCase {
	
	public void test(){
		ThreadPoolManager pool = new ThreadPoolManager();
		for(int i = 0; i < 50; i++){
			pool.addTask(new SimpleTask(i)); //SimpleTask实现了Task接口
		}
		try {
			Thread.sleep(70000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		pool.shutdown();
	}
	
}


ThreadPoolManager.startup()方法里面多加了一行,用于标记线程名字:
workThread.setName("WorkThread-" + i);

执行结果:
启动工作线程。。。
-----WorkThread-3---execute--SimpleTask[0] Begin...
-----WorkThread-3---execute--SimpleTask[0] End...
...
-----WorkThread-1---execute--SimpleTask[49] Begin...
-----WorkThread-1---execute--SimpleTask[49] End...
停止工作线程.
2 楼 xly_971223 2007-07-24  
ls这种方式倒是比较独特 用另外一种思路解决这个问题
1 楼 Qieqie 2007-07-24  
LZ的思路,是线程共享任务队列,线程按同步方法获取一个非空的任务执行:工作线程自己去“拉单”干。

我提供另外一种思路,线程是被动,由别人(监工)分配,激发:

有一个主线程--“监工”:负责查看任务队列中是否有任务,如果有,取出一个任务,设置到一个“空闲”的线程中,并notify该线程。

while (hasTask) {
   1、get the task from task quene 
   2、get an waiting worker thread, or create a new workder thread
   3、set the task to the thread, and set the thread status running
   synchronized(thread) {
       4、thread.nofity();//not notifyAll()
   }
}




线程类的run方法会是这样的:
synchronized(this) {
    while (!shutdown) {
        if (status == running) {
           1、run the task;
           2、task = null;
           3、status = waiting;
           4、manager.done(this, task);//告知监工自己已经完成这个任务
       }
       5、this.wait();
    }
}

相关推荐

    Windows下一个比较完美的线程池实现和示例

    Windows下一个比较完美的线程池实现和示例 本线程池提供了如下功能: 1.能根据任务个数和当前线程的多少在最小/最大线程个数之间自动调整(Vista后的系统有 SetThreadpoolThreadMaximum 等函数有类似功能); 2.能方便...

    Django异步任务线程池实现原理

    Django异步任务线程池实现原理主要涉及以下几个核心知识点: 1. 异步任务执行原理: 当Django应用在处理耗时的任务时,通常会阻塞主线程,导致用户在等待处理结果时无法进行其他操作。为了解决这个问题,Django采用...

    通过EasyExcel+线程池实现百万级数据从Excel导入到数据库

    在处理大量数据导入数据库的场景中,使用...通过以上步骤,可以利用EasyExcel和线程池实现百万级数据从Excel导入到数据库的功能。这种方式可以提高数据处理的效率,减少内存占用,并且能够更好地利用多核CPU的优势。

    简单C++线程池实现

    总结来说,这个简单的C++线程池实现是一个学习多线程和并发编程的好起点。它通过封装线程管理和任务调度,为开发者提供了一种更高效、更可控的方式来处理并发任务。在实际应用中,线程池可以被扩展以适应更复杂的...

    Linux C系统编程:使用线程池实现cp命令

    总结起来,Linux C系统编程中使用线程池实现类似`cp`命令的功能,是一个涉及多线程编程、任务调度和同步控制的综合实践。通过这样的实现,我们可以提高文件复制操作的并发性和效率,同时降低系统资源的消耗。在深入...

    c++线程池实现原理分析

    ### C++线程池实现原理分析 #### 一、引言 线程池是一种软件设计模式,用于管理和控制大量线程的创建与销毁,尤其是在处理大量短期任务时,它可以显著提高程序性能。线程池的核心思想是预先创建一组线程,并让它们...

    java 线程池实现多并发队列后进先出

    在"java 线程池实现多并发队列后进先出"这个主题中,我们关注的是线程池如何利用特定类型的队列来实现后进先出(LIFO,Last-In-First-Out)的行为。通常,线程池默认使用先进先出(FIFO,First-In-First-Out)的队列...

    Android下用线程池实现Http下载程序

    5. **异步下载**:通过线程池实现的下载是异步的,这意味着主线程不会被阻塞,用户界面仍然可以保持流畅。这是在Android中进行网络操作时必须遵循的原则,因为网络操作在主线程上执行会导致ANR(应用无响应)错误。 ...

    Python的线程池实现

    在本篇文章中,我们将深入探讨Python中的线程池实现,并参考提供的`ThreadPool.py`源码进行分析。 首先,Python标准库提供了一个名为`concurrent.futures`的模块,其中包含`ThreadPoolExecutor`类,它是实现线程池...

    基于win32的C++线程池实现

    以下将详细讲解基于Win32的C++线程池实现的关键概念和技术。 首先,我们需要理解Win32 API中的线程池接口。Windows提供了CreateThreadpool、SetThreadpoolCallbackPool、QueueUserWorkItem等函数来创建和管理线程池...

    使用线程池实现的Http上传下载实现

    前段时间发布了《Windows下一个比较完美的线程池实现和示例》(http://download.csdn.net/detail/fishjam/5106672),根据下载量和评论来看,对大家还比较有用。 现在发布一个利用该线程池实现的Http上传下载实现,...

    Java版线程池实现

    不过,上述代码展示的是一个自定义的线程池实现,它可能没有使用Java标准库中的`ExecutorService`。 这个自定义线程池的实现包括以下几个关键组件: 1. **线程池参数**: - `reserve`:保留线程数,这些线程不...

    c++ 线程池实现及安全队列

    下面是一个简化的线程池实现的伪代码: ```cpp class ThreadPool { public: void enqueue(std::function()&gt; task); // 提交任务 ~ThreadPool(); // 关闭线程池 private: std::vector&lt;std::thread&gt; workers; // ...

    基于win32的C++线程池实现(改进版)

    在"基于win32的C++线程池实现(改进版)"中,开发者已经针对上一版本的问题进行了修复,如崩溃和内存泄漏。这些问题是多线程编程中常见的挑战,崩溃可能是由于线程间的同步问题或者资源管理不当,而内存泄漏则可能导致...

    一个linux下的socket线程池实现

    本项目涉及的核心知识点是“Linux下的socket线程池实现”,这涉及到多个技术层面,包括socket编程、多线程技术和线程池的管理。 首先,让我们了解什么是Socket。Socket是网络通信的基本接口,它允许应用程序通过...

    Tomcat线程池实现简介

    Tomcat提供了两种线程池实现,一种是基于Apache Portable Runtime (APR)的Pool技术,另一种是纯Java实现的ThreadPool。本文主要探讨后者,即Java实现的线程池。 Java实现的线程池位于`tomcat-util.jar`中,初始化时...

    qt 线程池实现多线程下载

    本篇文章将深入讲解如何使用Qt的线程池实现多线程HTTP下载,并涵盖限速下载及进度显示的相关知识。 首先,我们要了解Qt中的线程池(QThreadPool)机制。QThreadPool是Qt提供的一个管理线程资源的类,它可以调度和...

    基于现代C++的高效线程池实现源码+项目文档说明(兼容Linux、macOS 和 Windows系统).zip

    基于现代C++的高效线程池实现源码+项目文档说明(兼容Linux、macOS 和 Windows系统).zip 【说明】 【1】项目代码完整且功能都验证ok,确保稳定可靠运行后才上传。欢迎下载使用!在使用过程中,如有问题或建议,请及时...

    线程池实现

    线程池实现

    socket 线程池实现(已经在项目中应用)

    本篇文章将深入讲解如何在Socket服务端实现线程池,以及其在实际项目中的应用。 首先,我们来看`SocketServer.java`。这个文件通常包含了服务器端的主逻辑,其中包括了服务器的启动、监听客户端连接和创建线程池来...

Global site tag (gtag.js) - Google Analytics