线程池(接上章补充)

接上文

并发编程

线程池

线程池就是创建若干个可执行的线程放入一个池(容器)中,有任务需要处理时,会提交到线程池中的任务队列,
处理完之后线程并不会被销毁,而是仍然在线程池中等待下一个任务。

线程池好处:

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

线程池流程

1 、判断核心线程池是否已满,没满则创建一个新的工作线程来执行任务。已满则。 2 、判断任务队列是否已满,
没满则将新提交的任务添加在工作队列,已满则。 3 、判断整个线程池是否已满,没满则创建一个新的工作线程来
执行任务,已满则执行饱和策略。
1 、判断线程池中当前线程数是否大于核心线程数,如果小于,在创建一个新的线程来执行任务,如果大于则
2 、判断任务队列是否已满,没满则将新提交的任务添加在工作队列,已满则。 3 、判断线程池中当前线程数是否
大于最大线程数,如果小于,则创建一个新的线程来执行任务,如果大于,则执行饱和策略。)

为什么使用线程池

new Thread的弊端如下:

  • 每次 new Thread 新建对象性能差
  • 内存空间被占用
  • 缺乏更多功能,如定时执行、定期执行、线程中断。
  • 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或 oom out of memory)

线程池实现 

newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
特征:
  • 工作线程的创建数量几乎没有限制 ( 其实也有限制的 , 数目为 Interger. MAX_VALUE), 这样可灵活的往线程池中
    添加线程。 如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间 ( 默认为 1 分钟 ) ,则该工
    作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
  • 在使用 CachedThreadPool 时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统
    瘫痪
public static void main(String[] args) {
    ThreadPool1 a = new ThreadPool1();
    ExecutorService executorService = Executors.newCachedThreadPool();
    int i = 0;
    for(;i<5;i++){
        try{
            Thread.sleep(1000);
        }catch (Exception e){
            e.printStackTrace();
        }
        executorService.execute(a);
    }
}
//发现5个线程都是使用的线程1,线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务
的线程,而不用每次新建线程。
 newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 newFixedThreadPool 固定线程池, 使用完毕必须手动关闭线程池, 否则会一直在内存中存在executorService.shutdown();// 关闭
public static void main(String[] args) {
    ThreadPool2 a = new ThreadPool2();
    // 创建定长的线程池
    ExecutorService executorService = Executors.newFixedThreadPool(5);
    int i = 0;
    for(;i<10;i++){
        /*try{
            Thread.sleep(1000);
        }catch (Exception e){
            e.printStackTrace();
        }*/
        System.out.println(i);
        executorService.execute(a);
    }
}
newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。
public static void main(String[] args) {
    ThreadPool3 a = new ThreadPool3();
    // 创建定长的线程池
    ScheduledExecutorService scheduledExecutorService =
    Executors.newScheduledThreadPool(5);
    int i = 0;
    for(;i<10;i++){
        // scheduledExecutorService.execute(a);
        // 延迟3秒执行
        // scheduledExecutorService.schedule(a,3,TimeUnit.SECONDS);
        // 先延迟5秒再每3秒执行一次
        scheduledExecutorService.scheduleWithFixedDelay(a,5,3,TimeUnit.SECONDS);
    }
}
newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序 (FIFO: 即先入先出 队列, LIFO: 后进先出 , 优先级 ) 执行。 程序的最后要调用一个存储过程,但是存储过程调用完需要花费很多的时间,程序并并不关心最后调的存储过程的 执行结果。所以想到最后重新开一个线程来调用储存过程 ,主线程直接返回结果。但是由于储存过程执行的时间很 长,所以用户同时访问的时候很容易出现几个调用存储过程的线程在后台同时运行,如果他们操作了同一张表的同 一条数据, 就容易导致死锁。所以我们希望调用存储过程的线程一次只有一个线程执行。这个时候就可以用只有一 个线程的线程池。
public static void main(String[] args) {
    ThreadPool4 a = new ThreadPool4();
    // 创建定长的线程池
    ScheduledExecutorService scheduledExecutorService =
    Executors.newSingleThreadScheduledExecutor();
    int i = 0;
    for(;i<10;i++){
        scheduledExecutorService.scheduleWithFixedDelay(a,5,3,TimeUnit.SECONDS);
    }
}

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值