线程池ThreadPool

●线程池的概述和使用

        程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时(长线程的应用?),更应该考虑使用线程池。线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。在JDK5之前,我们必须手动实现自己的线程池,从JDK5开始,Java内置支持线程池

线程池使用场景:

单个任务处理时间短,将需处理的任务数量大-->购票

 

1.使用new Thread()创建线程的弊端:

        每次通过new Thread()创建对象性能不佳。 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机。缺乏更多功能,如定时执行、定期执行、线程中断。

2.使用Java线程池的好处:

        重用存在的线程,减少对象创建、消亡的开销,提升性能。可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。

提供定时执行、定期执行、单线程、并发数控制等功能。

3.使用线程池目的:(降低线程创建销毁损耗)

线程池是面向后台程序
线程池是是为了提高内存和CPU效率
线程池有点类似于在服务端做优化

线程池是一次性创建一定数量的线程,当用请求过来不用去创建新的线程,直接使用已创建的线程,使用后又放回到线程池中
避免了频繁创建线程,及销毁线程的系统开销,提高是内存和CPU效率。

使用线程池的效率比较

package chapter;

import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


public class Demo {

//不使用线程池

    @Test
    public void test1() throws InterruptedException {
        Long start = System.currentTimeMillis();
        Random r = new Random();
        List<Integer> list= new ArrayList<>();
        for (int i = 0; i <100000 ; i++) {
            //创建100000个线程
            Thread t = new Thread(()->{
                list.add(r.nextInt());
            });
            t.start();
            t.join();
        }
        Long end = System.currentTimeMillis();
        System.out.println("用时:"+(end-start));
        System.out.println("list大小:"+list.size());
    }

//使用线程池:线程复用

    @Test
    public void test2() throws InterruptedException {
        Long start = System.currentTimeMillis();
        Random r = new Random();
        List<Integer> list= new ArrayList<>();
        //创建线程池
        ExecutorService pool= Executors.newSingleThreadExecutor();
        for (int i = 0; i <100000 ; i++) {
            //创建线程
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    list.add(r.nextInt());
                }
            });
        }
        pool.shutdown();
        pool.awaitTermination(1, TimeUnit.DAYS);
        Long end = System.currentTimeMillis();
        System.out.println("用时:"+(end-start));
        System.out.println("list大小:"+list.size());
        /**
         * test2的效率是test的200多倍
         */
    }
}

●内置线程池的概述

JDK一个Executors类(字面意思:执行者)来产生线程池,有如下几个方法:

●线程池的四种类型

newFixedThreadPool
  创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。

/*
        使用线程池(创建含有3个线程的线程池)
        直接先创建3个线程放入线程池中,等待使用
         */
        ExecutorService pool = Executors.newFixedThreadPool(3);

由于设置最大线程数为3,同时可以处理三个任务,超过3个任务的话,会出现线程的复用。

允许等待的时间是0秒

如果处理的线程数>核心线程数,大于线程等待时间,会终止前等待新的任务

newCachedThreadPool

创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。

 

 ExecutorService pool = Executors.newCachedThreadPool();
//里面有的线程数是Integer.MAX_VALUE=2,147,483,647条-->21亿+ 条非核心线程

newScheduledThreadPool (推荐)

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

1:可以先创建固定的线程数量

2:如果线程不够使用会开辟新的线程,一旦有闲置的线程就会自动接管

//创建定期任务执行的线程池
ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3);
    
//定期执行(延迟三秒执行)
scheduledThreadPool.schedule(new MyTask(),3, TimeUnit.SECONDS);

//定期重复执行(延迟1秒后每三秒执行一次)
scheduledThreadPool.scheduleAtFixedRate(new MyTask(),1,3,TimeUnit.SECONDS);

newSingleThreadExecutor

创建一个单线程化的线程池,以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程,那么如果需要,一个新线程将代替它执行后续的任务)。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。

底层使用LinkedBlockingQueue单向链表实现的阻塞队列,先进先出的顺序。支持多线程并发操作。LinkedBlockingQueue它如果不指定容量,默认为Integer.MAX_VALUE,也就是无界队列,多用于任务队列。

注意:newSingleThreadExecutornewFixedThreadPool的区别在于

newFixedThreadPool一个是固定线程数量一但发生异常就不会进行下去.

newSingleThreadExecutor一个属于单线程化线程永远且只有一个存在,发生异常会创建一个新的线程代替完成工作.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值