`
endual
  • 浏览: 3558977 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java 线程池

    博客分类:
  • java
 
阅读更多

 

2008 - 08 - 02

创建Java线程池

    博客分类:
  • Java

线程池的作用:

     线程池作用就是限制系统中执行线程的数量。
     根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程 排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程 池中有等待的工作线程,就可以开始运行了;否则进入等待队列。

 

为什么要用线程池:

  1. 减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务
  2. 可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)

线程池类

    

Java代码  收藏代码
  1. package  com.tdt.impl.ls;  
  2.   
  3. import  java.util.LinkedList;  
  4.   
  5. /**  
  6.  * @project LocationGateway  
  7.  * @author sunnylocus     
  8.  * @verson 1.0.0  
  9.  * @date   Aug 2, 2008  
  10.  * @jdk    1.4.2  
  11.  */   
  12. public   class  ThreadPool  extends  ThreadGroup {  
  13.     private   boolean  isClosed =  false ;   //线程池是否关闭    
  14.     private  LinkedList workQueue;       //工作队列   
  15.     private   static   int  threadPoolID =  1 ;   //线程池的id   
  16.     public  ThreadPool( int  poolSize) {   //poolSize 表示线程池中的工作线程的数量   
  17.   
  18.         super (threadPoolID +  "" );       //指定ThreadGroup的名称   
  19.         setDaemon(true );                //继承到的方法,设置是否守护线程池   
  20.         workQueue = new  LinkedList();   //创建工作队列   
  21.         for ( int  i =  0 ; i < poolSize; i++) {  
  22.             new  WorkThread(i).start();    //创建并启动工作线程,线程池数量是多少就创建多少个工作线程   
  23.         }  
  24.     }  
  25.       
  26.     /** 向工作队列中加入一个新任务,由工作线程去执行该任务*/   
  27.     public   synchronized   void  execute(Runnable task) {  
  28.         if (isClosed) {  
  29.             throw   new  IllegalStateException();  
  30.         }  
  31.         if (task !=  null ) {  
  32.             workQueue.add(task);//向队列中加入一个任务   
  33.             notify();           //唤醒一个正在getTask()方法中待任务的工作线程   
  34.         }  
  35.     }  
  36.       
  37.     /** 从工作队列中取出一个任务,工作线程会调用此方法*/   
  38.     private   synchronized  Runnable getTask( int  threadid)  throws  InterruptedException {  
  39.         while (workQueue.size() ==  0 ) {  
  40.             if (isClosed)  return   null ;  
  41.             System.out.println("工作线程" +threadid+ "等待任务..." );  
  42.             wait();             //如果工作队列中没有任务,就等待任务   
  43.         }  
  44.         System.out.println("工作线程" +threadid+ "开始执行任务..." );  
  45.         return  (Runnable) workQueue.removeFirst();  //反回队列中第一个元素,并从队列中删除   
  46.     }  
  47.       
  48.     /** 关闭线程池 */   
  49.     public   synchronized   void  closePool() {  
  50.         if (! isClosed) {  
  51.             waitFinish();        //等待工作线程执行完毕   
  52.             isClosed = true ;  
  53.             workQueue.clear();  //清空工作队列   
  54.             interrupt();        //中断线程池中的所有的工作线程,此方法继承自ThreadGroup类   
  55.         }  
  56.     }  
  57.       
  58.     /** 等待工作线程把所有任务执行完毕*/   
  59.     public   void  waitFinish() {  
  60.         synchronized  ( this ) {  
  61.             isClosed = true ;  
  62.             notifyAll();            //唤醒所有还在getTask()方法中等待任务的工作线程   
  63.         }  
  64.         Thread[] threads = new  Thread[activeCount()];  //activeCount() 返回该线程组中活动线程的估计值。   
  65.         int  count = enumerate(threads);  //enumerate()方法继承自ThreadGroup类,根据活动线程的估计值获得线程组中当前所有活动的工作线程   
  66.         for ( int  i = 0 ; i < count; i++) {  //等待所有工作线程结束   
  67.             try  {  
  68.                 threads[i].join();  //等待工作线程结束   
  69.             }catch (InterruptedException ex) {  
  70.                 ex.printStackTrace();  
  71.             }  
  72.         }  
  73.     }  
  74.   
  75.     /**  
  76.      * 内部类,工作线程,负责从工作队列中取出任务,并执行  
  77.      * @author sunnylocus  
  78.      */   
  79.     private   class  WorkThread  extends  Thread {  
  80.         private   int  id;  
  81.         public  WorkThread( int  id) {  
  82.             //父类构造方法,将线程加入到当前ThreadPool线程组中   
  83.             super (ThreadPool. this ,id+ "" );  
  84.             this .id =id;  
  85.         }  
  86.         public   void  run() {  
  87.             while (! isInterrupted()) {   //isInterrupted()方法继承自Thread类,判断线程是否被中断   
  88.                 Runnable task = null ;  
  89.                 try  {  
  90.                     task = getTask(id);     //取出任务   
  91.                 }catch (InterruptedException ex) {  
  92.                     ex.printStackTrace();  
  93.                 }  
  94.                 //如果getTask()返回null或者线程执行getTask()时被中断,则结束此线程   
  95.                 if (task ==  null return ;  
  96.                   
  97.                 try  {  
  98.                     task.run();  //运行任务   
  99.                 }catch (Throwable t) {  
  100.                     t.printStackTrace();  
  101.                 }  
  102.             }//  end while   
  103.         }//  end run   
  104.     }// end workThread   
  105. }  

 

2.测试类

 

Java代码  收藏代码
  1. package  com.tdt.test;  
  2.   
  3. import  com.tdt.impl.ls.ThreadPool;  
  4.   
  5. public   class  ThreadPoolTest {  
  6.       
  7.     public   static   void  main(String[] args)  throws  InterruptedException {  
  8.         ThreadPool threadPool = new  ThreadPool( 3 );  //创建一个有个3工作线程的线程池   
  9.         Thread.sleep(500 );  //休眠500毫秒,以便让线程池中的工作线程全部运行   
  10.         //运行任务   
  11.         for  ( int  i =  0 ; i <= 5  ; i++) {  //创建6个任务   
  12.             threadPool.execute(createTask(i));  
  13.         }  
  14.         threadPool.waitFinish(); //等待所有任务执行完毕   
  15.         threadPool.closePool(); //关闭线程池   
  16.   
  17.     }  
  18.   
  19.     private   static  Runnable createTask( final   int  taskID) {  
  20.         return   new  Runnable() {  
  21.             public   void  run() {  
  22.             //  System.out.println("Task" + taskID + "开始");   
  23.                 System.out.println("Hello world" );  
  24.             //  System.out.println("Task" + taskID + "结束");   
  25.             }  
  26.         };  
  27.     }  
  28. }  

 

 

结果:

Java代码  收藏代码
  1. 工作线程 0 等待任务...  
  2. 工作线程1 等待任务...  
  3. 工作线程2 等待任务...  
  4.   
  5. 工作线程0 开始执行任务...  
  6. Hello world  
  7. 工作线程0 等待任务...  
  8.   
  9. 工作线程1 开始执行任务...  
  10. Hello world  
  11. 工作线程1 等待任务...  
  12.   
  13. 工作线程2 开始执行任务...  
  14. Hello world  
  15. 工作线程2 等待任务...  
  16.   
  17. 工作线程0 开始执行任务...  
  18. Hello world  
  19. 工作线程0 等待任务...  
  20.   
  21. 工作线程1 开始执行任务...  
  22. Hello world  
  23. 工作线程1 等待任务...  
  24.   
  25. 工作线程2 开始执行任务...  
  26. Hello world  
  27. 工作线程2 等待任务...  

 

 

 

分享到:
评论
18 楼 sunnylocus 2011-09-06   引用
koone 写道
大概看明白了:这个就是生产消费模式吧,使用一个工作线程池和一个任务现场队列来完成的。不过没太明白,当加入了任务线程时是怎么样通知工作线程来工作的

此时的工作线程执行wait()方法后阻塞了,使用notify()方法通知工作线程干活
17 楼 koone 2011-09-04   引用
大概看明白了:这个就是生产消费模式吧,使用一个工作线程池和一个任务现场队列来完成的。不过没太明白,当加入了任务线程时是怎么样通知工作线程来工作的
16 楼 sunnylocus 2011-02-25   引用
wanghonghui023 写道
楼主有点像八一队的中锋-德嘞黑啊!

因为我长的黑,他们都说我是非洲人
15 楼 wanghonghui023 2011-02-25   引用
楼主有点像八一队的中锋-德嘞黑啊!
14 楼 sunnylocus 2010-05-13   引用
zerxd 写道
mht19840918 写道
又一轮子~

在1.5之后,是有更好的解决方案。不过在1.4这之前,这会是一个好的方法。

说的对!
13 楼 zerxd 2010-05-12   引用
mht19840918 写道
又一轮子~

在1.5之后,是有更好的解决方案。不过在1.4这之前,这会是一个好的方法。
12 楼 qn_lf 2010-04-30   引用
正好在找线程池  不过以前并发都考虑  SwingWorker模式
11 楼 mht19840918 2010-04-01   引用
又一轮子~
10 楼 haiya 2010-01-27   引用
getTask()那里等待我知道,问题是如果队列不是0呢?
不过很奇怪,我试了改了下那个createTask,里面的线程输出hello以后sleep5秒,然后试到它确实会等待前一个任务完成再去取新任务,不过我又不知道是哪里起的作用。
如下,System.out.println("Task running...");会在sleep完以后再输出

public void run() {
while(! isInterrupted()) {  //isInterrupted()方法继承自Thread类,判断线程是否被中断
Runnable task = null;
try {
task = getTask(id); //取出任务
}catch(InterruptedException ex) {
ex.printStackTrace();
}
//如果getTask()返回null或者线程执行getTask()时被中断,则结束此线程
if(task == null) return;

try {
task.run();  //运行任务
System.out.println("Task running...");
}catch(Throwable t) {
t.printStackTrace();
}
}//  end while
}//  end run
9 楼 sunnylocus 2010-01-27   引用
haiya 写道
我看你这段代码就是取了任务,让它自己去执行,然后自己又继续去取下一个任务,哪里有等待呢?
记得好像Effective Java的作者说过不推荐用ThreadGroup,说是实现不是太好。

while(! isInterrupted()) {  //isInterrupted()方法继承自Thread类,判断线程是否被中断  
                Runnable task = null;  
                try {  
                    task = getTask(id);     //取出任务  
                }catch(InterruptedException ex) {  
                    ex.printStackTrace();  
                }  
                //如果getTask()返回null或者线程执行getTask()时被中断,则结束此线程  
                if(task == null) return;  
                  
                try {  
                    task.run();  //运行任务  
                }catch(Throwable t) {  
                    t.printStackTrace();  
                }  
            }//  end while

看仔细些,取任务的时候用通过getTask()方法获取的,getTask()方法是从队列中取出一个任务,如果队列等于0,则调用 wait()方法将自身线程挂起。因为我以前用的jdk1.4,没有现成线程池就写了个,如果你用jdk1.5及以上版本就不用自己写了,因为都有现成的 线程池
8 楼 haiya 2010-01-27   引用
我看你这段代码就是取了任务,让它自己去执行,然后自己又继续去取下一个任务,哪里有等待呢?
记得好像Effective Java的作者说过不推荐用ThreadGroup,说是实现不是太好。

while(! isInterrupted()) {  //isInterrupted()方法继承自Thread类,判断线程是否被中断  
                Runnable task = null;  
                try {  
                    task = getTask(id);     //取出任务  
                }catch(InterruptedException ex) {  
                    ex.printStackTrace();  
                }  
                //如果getTask()返回null或者线程执行getTask()时被中断,则结束此线程  
                if(task == null) return;  
                  
                try {  
                    task.run();  //运行任务  
                }catch(Throwable t) {  
                    t.printStackTrace();  
                }  
            }//  end while
7 楼 sunnylocus 2010-01-27   引用
haiya 写道
工作线程会等待自己取得的任务完成以后再去取新的任务吗?

当然可以了,其实这就是经典的生产-消费者模式。如果队列里没有任务,消费线程会挂起,如果生产线程向队列加入新任务,生产线程会唤醒挂起的消费线程去队列中取任务。jdk1.5以后的版本有ThreadPoolExecutor线程池,可以直接拿来用
6 楼 haiya 2010-01-27   引用
工作线程会等待自己取得的任务完成以后再去取新的任务吗?
5 楼 sunnylocus 2010-01-14   引用
echozhjun 写道
不好意思,是可以的。敲错了代码

没关系,刚才我还纳闷代码我都测试过没问题,我以为与系统有关呢。
4 楼 echozhjun 2010-01-14   引用
不好意思,是可以的。敲错了代码
3 楼 echozhjun 2010-01-14   引用
我试了下你的程序,貌似不能closePool呀?
2 楼 sunnylocus 2009-11-02   引用
only_java 写道
可以自动或手动设置线程数量,么体现出来啊?

自动设置线程数量,可以根据CPU的数量来设定
int singleCPUcount =5
int totalThreadcount = Runtime.getRuntime().availableProcessors() * singleCPUcount
ThreadPool threadPool = new ThreadPool(totalThreadcount );
1 楼 only_java 2009-10-12   引用
可以自动或手动设置线程数量,么体现出来啊?
发表评论
表情图标

字体颜色:  字体大小:  对齐:
提示:选择您需要装饰的文字, 按上列按钮即可添加上相应的标签

(快捷键 Alt+S / Ctrl+Enter)

sunnylocus
搜索本博客
我的相册
我的留言簿 >>更多留言
  • 您好,请问一下为什么在每次发完短信之后都会报一下的异常: java.net.So ...
    -- by jiangzhou556
  • 您好!能不能加一下QQ(316171399)有几个关于联通短信网关的问题问你一下
    -- by jiangzhou556
  • 刚刚加你QQ 和msn了,请加下我呗,想了解一下sgip接收这块,非常感谢
    -- by yjpwy
存档
  • Rss
  • Rss_google

声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。若作者同意转载,必须以超链接形式标明文章原始出处和作者。
© 2003-2011 ITeye.com. All rights reserved. [ 京ICP证110151号 京公网安备110105010620 ]

分享到:
评论

相关推荐

    java线程池使用后到底要关闭吗

    java线程池使用后到底要关闭吗 java线程池是一种高效的并发编程技术,可以帮助开发者更好地管理线程资源,提高系统的性能和可靠性。然而,在使用java线程池时,一个常见的问题是:使用完线程池后到底要不要关闭?...

    java线程池完整代码

    "Java 线程池完整代码解析" Java 线程池是 Java 语言中的一个重要概念,它允许开发者创建和管理多个线程,以提高程序的并发性和性能。下面是对给定文件的解析,包括 title、description、标签和部分内容的解析。 ...

    java线程池封装j

    Java线程池是一种高效管理线程的技术,它允许开发者预定义一组线程,根据任务的需要灵活调度,而不是每次需要执行任务时都创建新的线程。这种设计模式大大提高了系统的性能,减少了系统资源的消耗,特别是在高并发...

    java线程池知识.ppt

    java线程池知识、

    java线程池实例详细讲解

    Java线程池是一种高效管理线程资源的工具,它能够帮助开发者有效地控制并调度线程,从而提升系统性能,减少系统资源的浪费。在Java中,`ExecutorService`接口是线程池的主要入口,它是`java.util.concurrent`包的一...

    Java线程池使用说明

    Java线程池是Java并发编程中的重要组件,它能够有效地管理和复用线程,从而提高程序的执行效率和降低资源消耗。在JDK 1.5版本之前,Java对线程池的支持非常有限,而在JDK 1.5之后,加入了java.util.concurrent包,...

    java线程池threadpool简单使用源码

    Java线程池(ThreadPool)是Java并发编程中的一个重要概念,它可以帮助我们有效地管理和控制并发执行的任务,从而提高系统的效率和稳定性。线程池通过复用已存在的线程,避免了频繁创建和销毁线程带来的开销,同时也...

    自定义实现Java线程池

    ### 自定义实现Java线程池 #### 一、概述 在深入探讨自定义Java线程池之前,我们先简要回顾一下线程池的基本概念及其重要性。线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动...

    java线程池的源码分析.zip

    Java线程池是Java并发编程中的重要组成部分,它在多线程和高并发场景下扮演着关键角色。本文将深入探讨Java线程池的源码分析,并对比不同类型的线程池,以帮助开发者更好地理解和利用这一强大的工具。 首先,我们要...

    Java 线程池.docx

    Java线程池是一种高效管理线程资源的工具,它的出现是为了应对多线程编程中频繁创建和销毁线程带来的性能开销以及资源消耗。在Java中,通过使用线程池,我们可以预先创建一定数量的线程,这些线程在空闲时可以被复用...

    Java线程池与ThreadPoolExecutor.pdf

    Java线程池是Java并发编程中的重要组成部分,它允许开发者管理多个线程并有效地调度任务。线程池通过ThreadPoolExecutor类实现,这是一个高度可配置的工具,能够根据具体需求定制线程的创建、管理和销毁策略。 ...

    Java简单线程池 线程池中文文档

    简单的线程池程序+中文文档 包结构: com.tangkai.threadpool --SimpleThread.java 工作线程 --TestThreadPool.java 程序入口 --ThreadPoolManager.java 线程池管理类

    Java 线程池的原理与实现

    Java线程池是一种高级的多线程处理框架,它是Java并发编程中非常重要的一个组件。线程池的原理和实现涉及到操作系统调度、内存管理和并发控制等多个方面。理解线程池的工作原理有助于优化程序性能,避免过度创建和...

    一个通用的Java线程池类

    2.然后根据提示运行java命令执行示例程序,观看线程池的运行结果 目标:Java中多线程技术是一个难点,但是也是一个核心技术。因为Java本身就是一个多线程语言。本人目前在给46班讲授Swing的网络编程--使用Swing来...

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

    Java线程池是一种高效管理并发任务的机制,它允许开发者预先配置一定数量的线程,以便在处理多个并发任务时能有效地复用这些线程,从而避免了频繁创建和销毁线程带来的开销。在Java中,`java.util.concurrent`包下的...

    基于Java线程池技术实现Knock Knock游戏项目.zip

    基于Java线程池技术实现Knock Knock游戏项目.zip 基于Java线程池技术实现Knock Knock游戏项目.zip 基于Java线程池技术实现Knock Knock游戏项目.zip 基于Java线程池技术实现Knock Knock游戏项目.zip 基于Java线程池...

    JAVA线程池的原理与实现.pdf

    Java线程池是一种高效利用系统资源、管理并发执行任务的机制。它的原理是通过预先创建一组线程,这些线程在任务到来时可以立即执行,而不是每次需要执行任务时都新建线程,从而降低了线程创建和销毁带来的开销。...

    Java线程池及观察者模式解决多线程意外死亡重启问题

    Java线程池是Java并发编程中的重要组成部分,它允许开发者高效地管理多个并发执行的线程,有效地控制系统的资源消耗,提高系统性能和稳定性。在Java中,`java.util.concurrent`包提供了`ExecutorService`接口及其...

    Java 线程池.pptx

    讲述了java线程池的优点,参数,6种线程池的使用场景,线程池用到的handler,线程任务的提交方式等等。

Global site tag (gtag.js) - Google Analytics