码迷,mamicode.com
首页 > 编程语言 > 详细

关于线程池

时间:2016-07-08 18:18:46      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:

 

关于线程池

demo,请用intellij idea 打开,或者用文本编辑查看代码

线程池的作用

线程池作用就是限制系统中执行线程的数量。      根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费系统资源,多了造成系统拥挤效率不高。

当一个新任务需要运行时,如果线程 池中有等待的工作线程,就可以开始运行了;否则进入等待队列。  为什么要用线程池: 减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务 可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

虽然线程之间切换的调度开销很小,但如果有很多线程,环境切换也可能严重地影响程序的性 能。因为线程的生成关闭很浪费资源 所以不要频繁的创建新线程而是使用线程池。

线程池就是管理线程的地方, 不用了线程池可以让它休眠 而且比你管理的要好的多。线程池为线程生命周期开销问题和资源不足问题提供了解决方案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。其好处是,因为在请求到达时线程已经存在,所以无意中也消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使应用程序响应更快。而且,通过适当地调 整线程池中的线程数目,也就是当请求的数目超过某个阈值时,就强制其它任何新到的请求一直等待,直到获得一个线程来处理为止,从而可以防止资源不足。 

Executor详解:  Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。ThreadPoolExecutor是Executors类的底层实现。我们先介绍下Executors。  Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利。为了编写高效稳定可靠的多线程程序,线程部分的新增内容显得尤为重要。

  有关Java5线程新特征的内容全部在java.util.concurrent下面,里面包含数目众多的接口和类,熟悉这部分API特征是一项艰难的学习过程。目前有关这方面的资料和书籍都少之又少,大所属介绍线程方面书籍还停留在java5之前的知识层面上。

  当然新特征对做多线程程序没有必须的关系,在java5之前通用可以写出很优秀的多线程程序。只是代价不一样而已。

  线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。

  在Java5之前,要实现一个线程池是相当有难度的,现在Java5为我们做好了一切,我们只需要按照提供的API来使用,即可享受线程池带来的极大便利。

  Java5的线程池分好多种:固定尺寸的线程池、可变尺寸连接池。

  在使用线程池之前,必须知道如何去创建一个线程池,在Java5中,需要了解的是java.util.concurrent.Executors类的API,这个类提供大量创建线程池的静态方法,是必须掌握的。  实

一、固定大小的线程池

Java代码

 
 
 
 
 
xxxxxxxxxx
 
 
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
?
for (int i = 1; i <= 10; i++) {
    final int index = i;
    fixedThreadPool.execute(new Runnable() {
      @Override
          public void run() {
               String threadName = Thread.currentThread().getName();
               System.out.println("zxy, 线程:"+threadName+",正在执行第" + index + "个任务");
               try {
                  Random random = new Random(System.currentTimeMillis());
                  int r = random.nextInt(3) + 1;
 
                  Thread.sleep(r*1000);
               } catch (InterruptedException e) {
                  e.printStackTrace();
             }
         }
     });
 }
 

第一行代码,创建了一个包含3个线程的线程池。下面的代码是用来测试这个线程池是如何工作的,for循环共创建了10个任务,每个任务所需时间不等。由于线程池中只有3个线程,所以从第四个任务就需要等待前面有任务被执行完,有空余线程的时候才能开始。

二、单任务线程池

  在上例的基础上改一行创建pool对象的代码为:

  //创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。 Java代码

 
 
 
 
 
xxxxxxxxxx
 
 
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
 
//下面的测试代码和上面的相同
 

 

  对于以上两种连接池,大小都是固定的,当要加入的池的线程(或者任务)超过池最大尺寸时候,则入此线程池需要排队等待。

  一旦池中有线程完毕,则排队等待的某个线程会入池执行。

三、可变尺寸的线程池

  与上面的类似,只是改动下pool的创建方式:

  //创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。 Java代码

 
 
 
 
 
 
 
 
 
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
 

 

四、延迟连接池

Java代码

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
//延迟2秒后执行该任务
scheduledThreadPool.schedule(new Runnable() {
    @Override
      public void run() {
           System.out.println("我是两秒后执行的那个线程");
      }
}, 2, TimeUnit.SECONDS);
//延迟1秒后,每隔2秒执行一次该任务
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
     @Override
     public void run() {
           System.out.println("我是一秒后执行的那个线程,注意每隔两秒我会出现一次");
     }
}, 1, 2, TimeUnit.SECONDS);

 

五、单任务延迟连接池

  在四代码基础上,做改动

  //创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。

Java代码

 
 
 
 
 
xxxxxxxxxx
 
 
ScheduledExecutorService singleThreadScheduledPool = Executors.newSingleThreadScheduledExecutor();
//延迟1秒后,每隔2秒执行一次该任务
singleThreadScheduledPool.scheduleAtFixedRate(new Runnable() {
     @Override
     public void run() {
         String threadName = Thread.currentThread().getName();
         System.out.println("zxy, 线程:" + threadName + ",正在执行");
     }
 
 },1,2, TimeUnit.SECONDS);
 

 

六、使用线程池的构造方法创建线程池

  Java代码

 
 
 
 
 
xxxxxxxxxx
 
 
    BlockingQueue bqueue = new ArrayBlockingQueue(20);
    ThreadPoolExecutor pool = new ThreadPoolExecutor(2,3,2, TimeUnit.MILLISECONDS,bqueue);  //创建一个核心线程数为2,最多为3,多余核心线程数的线程的存活时间为2毫秒,创建的线程放到bqueue队列中
?
    for (int i = 1; i <= 10; i++) {
        final int index = i;
        pool.execute(new Runnable() {
            @Override
            public void run() {
                String threadName = Thread.currentThread().getName();
                System.out.println("zxy, 线程:"+threadName+",正在执行第" + index + "个任务");
                try {
                    Random random = new Random(System.currentTimeMillis());
                    int r = random.nextInt(3) + 1;
                    Thread.sleep(r*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
 
        });
 

  

 

关于线程池

标签:

原文地址:http://www.cnblogs.com/waj6701/p/5654032.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!