java线程池简单实例

多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。但如果对多线程应用不当,会增加对单个任务的处理时间。可以举一个简单的例子:

假设在一台服务器完成一项任务的时间为T

      T1 创建线程的时间        T2 在线程中执行任务的时间,包括线程间同步所需时间        T3 线程销毁的时间  

显然T = T1+T2+T3。注意这是一个极度简化的假设。

可以看出T1,T3是多线程本身的带来的开销,我们渴望减少T1,T3所用的时间,从而减少T的时间。但一些线程的使用者并没有注意到 这一点,所以在程序中频繁的创建或销毁线程,这导致T1和T3在T中占有相当比例。显然这是突出了线程的弱点(T1,T3),而不是优点(并发性)。

线程池技术正是关注如何缩短或调整T1,T3时间的技术,从而提高服务器程序性能的。它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了。

线程池不仅调整T1,T3产生的时间段,而且它还显著减少了创建线程的数目。在看一个例子:

假设一个服务器一天要处理50000个请求,并且每个请求需要一个单独的线程完成。我们比较利用线程池技术和不利于线程池技术的服务器 处理这些请求时所产生的线程总数。在线程池中,线程数一般是固定的,所以产生线程总数不会超过线程池中线程的数目或者上限(以下简称线程池尺寸),而如果 服务器不利用线程池来处理这些请求则线程总数为50000。一般线程池尺寸是远小于50000。所以利用线程池的服务器程序不会为了创建50000而在处 理请求时浪费时间,从而提高效率。

这些都是假设,不能充分说明问题,下面我将讨论线程池的简单实现并对该程序进行对比测试,以说明线程技术优点及应用领域。

一般一个简单线程池至少包含下列组成部分

线程池管理器(ThreadPoolManager):用于创建并管理线程池

工作线程(WorkThread): 线程池中线程

任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行。

任务队列:用于存放没有处理的任务。提供一种缓冲机制。

 

线程池管理器至少有下列功能:创建线程池,销毁线程池,添加新任务。下面就是小弟的实现,还是欢迎拍砖哈:

 代码如下 复制代码
public class ThreadPoolManager {
    private static ThreadPoolManager instance = null;
    private List<Upload> taskQueue = Collections.synchronizedList(new LinkedList<Upload>());//任务队列
    private WorkThread[] workQueue ;    //工作线程(真正执行任务的线程)
    private static int worker_num = 5;    //工作线程数量(默认工作线程数量是5)
    private static int worker_count = 0;
   
    private ThreadPoolManager(){
        this(5);
    }
    private ThreadPoolManager(int num){
        worker_num = num;
        workQueue = new WorkThread[worker_num];
        for(int i=0;i<worker_num;i++){
            workQueue[i] = new WorkThread(i);
        }
    }
   
    public static synchronized ThreadPoolManager getInstance(){
        if(instance==null)
            instance = new ThreadPoolManager();
        return instance;
    }
   
    public void addTask(Upload task){
        //对任务队列的操作要上锁
        synchronized (taskQueue) {
            if(task!=null){
                taskQueue.add(task);
                taskQueue.notifyAll();
                System.out.println("task id "+task.getInfo() + " submit!");
            }
               
        }
    }
   
    public void BatchAddTask(Upload[] tasks){
        //对任务队列的修改操作要上锁
        synchronized (taskQueue) {
            for(Upload e:tasks){
                if(e!=null){
                    taskQueue.add(e);
                    taskQueue.notifyAll();
                    System.out.println("task id "+e.getInfo() + " submit!");
                }
            }       
        }
    }
   
    public void destory(){
        System.out.println("pool begins to destory ...");
        for(int i = 0;i<worker_num;i++){
            workQueue[i].stopThread();
            workQueue[i] = null;
        }
        //对任务队列的操作要上锁
        synchronized (taskQueue) {
            taskQueue.clear();
        }
       
        System.out.println("pool ends to destory ...");
    }
   
    private class WorkThread extends Thread{
        private int taksId ;
        private boolean isRuning = true;
        private boolean isWaiting = false;
       
       
        
        public WorkThread(int taskId){
            this.taksId= taskId;
            this.start();
        }
       
        public boolean isWaiting(){
            return isWaiting;
        }
        // 如果任务进行中时,不能立刻终止线程,需要等待任务完成之后检测到isRuning为false的时候,退出run()方法
        public void stopThread(){
            isRuning = false;
        }
       
        @Override
        public void run() {
            while(isRuning){
                Upload temp = null;
                //对任务队列的操作要上锁
                synchronized (taskQueue) {
                    //任务队列为空,等待新的任务加入
                    while(isRuning&&taskQueue.isEmpty()){
                        try {
                            taskQueue.wait(20);
                        } catch (InterruptedException e) {
                            System.out.println("InterruptedException occre...");
                            e.printStackTrace();
                        }
                    }
                    if(isRuning)
                        temp = taskQueue.remove(0);
                }
                //当等待新任务加入时候,终止线程(调用stopThread函数)造成 temp = null
                if(temp!=null){
                    System.out.println("task info: "+temp.getInfo()+ " is begining");
                    isWaiting = false;
                    temp.uploadPic();
                    isWaiting = true;
                    System.out.println("task info: "+temp.getInfo()+ " is finished");
                }   
            }
        }
    }
}

然后定义任务接口(Task):这里我定义的是上传图片的功能接口(这里用抽象类或者接口随你自己).

 代码如下 复制代码

Upload public abstract class Upload {
    protected String info;
    abstract boolean uploadPic();
    public String getInfo(){
        return info;
    }
}

然后定义具体任务类:我这里简单,让它睡眠2s。当然你也可以定义很多实现Upload的任务类。

 代码如下 复制代码
TaskUpload public class TaskUpload extends Upload {
   
    public TaskUpload(String info){
        this.info = info;
    }
    public String getInfo(){
        return info;
    }
    @Override
    public boolean uploadPic()  {
        // TODO Auto-generated method stub
        System.out.println(info+"sleep begin ....");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(info+"sleep end ....");
        return false;
    }
}

最后,测试这个简单的线程池:

 代码如下 复制代码

public class ThreadPoolManagerTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Upload[] tasks = createBatchTask(7);
        ThreadPoolManager pool = ThreadPoolManager.getInstance();
        pool.BatchAddTask(tasks);
        pool.destory();
    }
    private static Upload[] createBatchTask(int n){
        Upload[] tasks = new TaskUpload[n];
        for(int i = 0;i<n ;i++ ){
            tasks[i] = new TaskUpload("task id is "+ i);
        }
        return tasks;
    }
}

时间: 2024-08-05 15:32:53

java线程池简单实例的相关文章

Java 线程池简单例子使用说明

注:处理机制    当一个任务通过execute(Runnable)方法欲添加到线程池时:    如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务.    如果此时线程池中的数量等于corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列.    如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处

Java线程池的几种实现方法和区别介绍_java

Java线程池的几种实现方法和区别介绍 import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.E

Java线程池的几种实现方法及常见问题解答_java

工作中,经常会涉及到线程.比如有些任务,经常会交与线程去异步执行.抑或服务端程序为每个请求单独建立一个线程处理任务.线程之外的,比如我们用的数据库连接.这些创建销毁或者打开关闭的操作,非常影响系统性能.所以,"池"的用处就凸显出来了. 1. 为什么要使用线程池 在3.6.1节介绍的实现方式中,对每个客户都分配一个新的工作线程.当工作线程与客户通信结束,这个线程就被销毁.这种实现方式有以下不足之处: •服务器创建和销毁工作的开销( 包括所花费的时间和系统资源 )很大.这一项不用解释,可以

Java线程池类ThreadPoolExecutor、ScheduledThreadPoolExecutor及Executors工厂类

Java中的线程池类有两个,分别是:ThreadPoolExecutor和ScheduledThreadPoolExecutor,这两个类都继承自ExecutorService.利用这两个类,可以创建各种不同的Java线程池,为了方便我们创建线程池,Java API提供了Executors工厂类来帮助我们创建各种各样的线程池.下面我们分别介绍一下这三个类. Java线程池ExecutorService继承树: 一.ThreadPoolExecutor ThreadPoolExecutor是Exe

Java线程池架构2-多线程调度器(ScheduledThreadPoolExecutor)

在前面介绍了java的多线程的基本原理信息:<Java线程池架构原理和源码解析(ThreadPoolExecutor)>,本文对这个java本身的线程池的调度器做一个简单扩展,如果还没读过上一篇文章,建议读一下,因为这是调度器的核心组件部分.   我们如果要用java默认的线程池来做调度器,一种选择就是Timer和TimerTask的结合,在以前的文章:<Timer与TimerTask的真正原理&使用介绍>中有明确的说明:一个Timer为一个单独的线程,虽然一个Timer可

Java线程池架构(二)多线程调度器

在前面介绍了java的多线程的基本原理信息:<Java线程池架构原理和源码解析>,本文对这个java本身的线程池的调度器做一个简单扩展,如果还没读过上一篇文章,建议读一下,因为这是调度器的核心组件部分. 我们如果要用java默认的线程池来做调度器,一种选择就是Timer和TimerTask的结合,在以前的文章:<Timer与 TimerTask的真正原理&使用介绍>中有明确的说明:一个Timer为一个单独的线程,虽然一个Timer可以调度多个 TimerTask,但是对于一

Java线程池 ExecutorService

本篇主要涉及到的是java.util.concurrent包中的ExecutorService.ExecutorService就是Java中对线程池的实现. 一.ExecutorService介绍 ExecutorService是Java中对线程池定义的一个接口,它java.util.concurrent包中,在这个接口中定义了和后台任务执行相关的方法: Java API对ExecutorService接口的实现有两个,所以这两个即是Java线程池具体实现类(详细了解这两个实现类,点击这里):

java线程池当其中一个线程算出结果,终止全部线程

问题描述 java线程池当其中一个线程算出结果,终止全部线程 业务逻辑: 一个大型社区,每一秒有上千人在提交留言,提交的留言将经过,上万条的正则表达式的过滤,没有匹配任何规则的,才保存到系统,否则提示用户,您录入的内容不合法. 我是这样想的,把这上万条正则表达式,拆分成2000条一组,开一个5个线程的线程池,每个线程将负责其中2000个规则的匹配. 每条留言提交时,将由这5个线程,去判断是否有匹配的规则,如果其中一个线程匹配到了规则,将结束其他4个线程的任务,返回给用户结果. 请问这种要怎么实现

Java 线程池的原理与实现

这几天主要是狂看源程序,在弥补了一些以前知识空白的同时,也学会了不少新的知识(比如 NIO),或者称为新技术吧.线程池就是其中之一,一提到线程,我们会想到以前<操作系统>的生产者与消费者,信号量,同步控制等等.一提到池,我们会想到数据库连接池,但是线程池又如何呢? 建议:在阅读本文前,先理一理同步的知识,特别是syncronized同步关键字的用法.关于我对同步的认识,要缘于大三年的一本书,书名好像是 Java 实战,这本书写得实在太妙了,真正的从理论到实践,从截图分析到.class字节码分析