Java 多线程之线程池--学习笔记

线程池存在的原因
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
线程池分类:线程池执行器、可调度线程池执行器,"分而治之"
在这里插入图片描述
ThreadPoolExecutor的三个实现子类:(以下三个子类虽然功能不同但是其实都是利用ThreadPoolExecutor来创建线程池的)
newCachedThreadPool:
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用他们,并在需要时使用提供的ThreadFactory创建新线程
特征:
1.线程池中数量没有固定,可达到最大值(Integer.MAX.VALUE)
2.线程池中的线程可进行缓存重复利用和回收,回收默认时间为1分钟
3.当线程池中没有可用的线程,会重新创建一个线程


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CacheThreadPoolDemo {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();//创建一个线程池,左侧是该方法的返回值,Executors为接口
        for(int i = 0;i<20;i++){
            executorService.execute(new Task());//提交线程
        }
        executorService.shutdown();
    }

}

public class Task implements Runnable {
    @Override
    public void run() {
//        try {
//            Thread.sleep(1000);
//        } catch (InterruptedException e) {   //不加休眠时间,不会出现20个线程,因为之前用完的线程会重新被调用
//            e.printStackTrace();
//        }
        System.out.println(Thread.currentThread().getName()+" running");
    }
}

newFixedThreadPool:创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数nThreads线程会处于处理任务的活动状态,如果在所有线程处于活动状态时提交附加任务,则在 有可用线程之前,附加任务将在队列中等待,如果在关闭前的执行期间由于任务失败而导致任何线程终止 ,那么一个新线程将代替它执行后序的任务。
特征:
1.线程池中的线程处于一定的量,可以很好的控制并发量
2.线程可以重复被使用,在显示关闭之前,都将一直存在
3.超出一定量的线程被 提交时候需要在队列中等待

public class FixedThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for (int i = 0 ;i<20;i++){
            executorService.execute(new Task());
        }
        executorService.shutdown();
    }
}

Task 类如上

newSingleThreadExecutor:
创建一个使用worker线程的Excutor,以无界队列方式来运行该线程(注意:如果因为在关闭前的执行期间出现失败而终止了此单个线程,那么如果需要,一个线程将替代它执行后序任务)。可保证顺序的执行各个任务,并且在任意给定的时间不会有多个线程是活动的。与其他等效的newFixedTreadPool(1)不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程
特征:
1.线程池中最多执行一个线程,之后提交的线程活动将会排在队列中依次执行

public class SingleThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for(int i = 0;i<20;i++){
            executorService.execute(new Task());
        }
        executorService.shutdown();
    }
}

Task如上

ScheduledThreadPoolExcutor 可调度线程池 可以实现延迟、定时等,其两个实现子类newScheduledThreadPool、newSingleScheduledThreadPool
newScheduledThreadPool:创建一个线程池,它可安排在给定延迟后运行命令或者定期的执行
特征:
1.线程池中具有指定数量的线程,即便是空线程也将保留
2.可定时或者延迟执行线程活动
newSingleScheduledThreadPool:创建一个单线程执行程序,它科技安排在给定延迟后运行命令或者定期地执行
特征:
1.线程池中最多执行1个线程,之后提交的线程活动将会排在队列中依次执行
2.可定时或者延迟执行线程活动

//DEMO实现延迟三秒
public class ScheduledThreadPoolDemo {
    public static void main(String[] args) {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
        System.out.println(System.currentTimeMillis());
        scheduledExecutorService.schedule(new Runnable() {  //此时使用schedule方法提交线程
            @Override
            public void run() {
                System.out.println("延迟三秒执行");
                System.out.println(System.currentTimeMillis());
            }
        },3, TimeUnit.SECONDS);
        scheduledExecutorService.shutdown();
    }
}

//demo2实现延迟1秒,每三秒还有继续执行
public class ScheduledThreadPoolDemo2 {
    public static void main(String[] args) {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
        System.out.println(System.currentTimeMillis());
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {//调用方法也改变
            @Override
            public void run() {
                System.out.println("1------延迟一秒执行,每三秒执行一次");
                System.out.println(System.currentTimeMillis());
            }
        },1,3, TimeUnit.SECONDS);              //参数改变
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("2------延迟一秒执行,每三秒执行一次");
                System.out.println(System.currentTimeMillis());
            }
        },1,3, TimeUnit.SECONDS);
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("3-------延迟一秒执行,每三秒执行一次");
                System.out.println(System.currentTimeMillis());
            }
        },1,3, TimeUnit.SECONDS);
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("4--------延迟一秒执行,每三秒执行一次");
                System.out.println(System.currentTimeMillis());
            }
        },1,3, TimeUnit.SECONDS);
//        scheduledExecutorService.shutdown();
    }
}

newWorkStealingPool
创建一个带并行级别的线程池,并行级别决定了同一时刻最多有多少个线程在执行,如不传并行级别参数,将默认为当前系统的CPU个数

线程池的生命周期
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果现有线程数大于核心线程池的大小,小于线程池能创建线程的最大个数,则可以继续创建线程

在这里插入图片描述
arrayblockingqueue和linkedblockqueue的区别:(重要!!!)
1.队列中锁的实现不同
ArrayBlockingQueue实现的队列中的锁是没有分离的,即生产和消费用的是同一个锁
LinkedBlockingQueue实现的队列中的锁是分离的,即生产者用的是putLock,消费者用的是takeLock
2.队列大小初始化方式不同
ArrayBlockingQueue实现的队列必须指定队列的大小(底层结构为数组)
LinkBlockiingQueue实现的队列中可以不指定队列的大小,但是默认是Inter.MAX_VALUE

在这里插入图片描述
第一种拒绝策略比较好,为默认拒绝策略在这里插入图片描述
在这里插入图片描述
(执行逻辑------重要!!!)
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值