精华内容
下载资源
问答
  • java线程池设计原理
    2020-05-24 23:42:00

    线程池的构造函数有7个参数

    1、corePoolSize 线程池核心线程大小
    2、maximumPoolSize 线程池最大线程数量
    3、keepAliveTime 空闲线程存活时间
    4、unit 空间线程存活时间单位
    5、workQueue 工作队列
    6、threadFactory 线程工厂–创建线程
    7、handler 拒绝策略 – 线程池满时的策略

    创建顺序

    核心线程 -> 队列 -> 最大线程 -> 拒绝策略

    workQueue

    ArrayBlockingQueue 基于数组的有界阻塞队列
    LinkedBlockingQuene 基于链表的无界阻塞队列
    SynchronousQuene 一个不缓存任务的阻塞队列
    PriorityBlockingQueue 具有优先级的无界阻塞队列

    一句话理解线程池

    线程复用,减少线程创建、销毁带来的CPU压力。

    本质 (核心) :
    消费者模式

    开了线程 不关闭 ,获取任务(Runnable 对象)来执行。
    执行完后,线程阻塞,但不销毁。
    任务多了就放到阻塞队列

    原理很简单

    你可以通过消费者模式写一个简单的线程池

    更多相关内容
  • 自定义实现Java线程池

    2018-09-22 20:59:38
    自定义实现Java线程池,学习大师设计思想,瞻仰大神笔法
  • 当我要去了解Java线程池设计思想时候,网上的讲解都是没有讲解到核心问题,大多数都是贴代码讲解,没办法我只能去调试jdk中源码来了解,本文是给我有一样疑问的人讲解线程池设计思想,而不是针对具体实现。...

    当我要去了解Java线程池设计思想时候,网上的讲解都是没有讲解到核心问题,大多数都是贴代码讲解,没办法我只能去调试jdk中源码来了解,本文是给我有一样疑问的人讲解线程池设计思想,而不是针对具体实现。

    线程池的演进

    1. 现在需要创建大量的任务,给出一个场景思考,假设需要处理10000个任务,如下图所示,我们来分析一下以下传统方式的弊端

    在这里插入图片描述

    • 问题1)假设当前电脑为4核处理器,理想状态是创建4个或8个任务比较好(这里的数量只是简单说明,不用深究),那么,当线程数量超过8个以后将会下降,因为CPU会频繁切换,为了保持当前线程的上下文(可以理解为当前线程的状态,包括执行代码的位置和数据的保存),所以线程的数量对线程的影响还是比较大的。
      在这里插入图片描述
    • 问题2)线程(英语:thread)是操作系统能够进行运算调度的最小单位。也就是说,要执行一次任务,需要为这个任务准备基本的资源,比如说内存、IO等。那么完成一次任务的过程,实际有效的也就是任务执行的时间,如下图所示
      在这里插入图片描述
      也就是,当前线程执行的效率为=执行线程/(创建线程+执行线程+销毁线程),当我们需要创建10000个线程,那么将会有很多的开销
    • 问题3)创建大量线程内存空间的开销,当前我们创建的10000个线程,或许还可以创建出来,假设现在需要创建1000000000个线程呢?那么JVM会不会挂掉?如何优化?

    针对以上问题,引入JDK中ThreadPoolExecutor 的线程池设计思想

    ThreadPoolExecutor设计思想

    线程池设计核心思想包括两部分,如下图所示

    在这里插入图片描述

    • 工作线程Worker,实现线程Thread执行类,执行任务从定义任务或者任务队列中获取
    • 任务队列,当工作线程Worker数据为3时候,当前定义任务为10个,那么当工作线程Worker还未执行完毕,多余的7个任务将存储在任务队列上

    回顾线程池如何传统线程问题

    1. 线程数量
    2. 线程的创建和销毁
    3. 大量线程创建与jvm关系

    由于引入工作线程Worker,线程中的数量明确控制,解决问题1。工作线程Worker是从任务队列或定义任务中拿取任务执行,所有不会频繁的创建线程和销毁,解决问题2.引入任务队列,当任务队列存储大小固定,这里举例为100,那么当任务超过100后,将采集策略,如拒绝任务的执行,直接丢弃、或者抛出异常等方法,解决问题3

    总结

    以上为线程池大概思路,不涉及具体细节实现,对于了解线程池设计可以了,基于以上思想,可以自实行线程池,接下来,将简单分析一下jdk源码,将线程池思想落地链接:Java线程池核心代码分析 jdk1.8 (ThreadPoolExecutor 二)

    展开全文
  • NULL 博文链接:https://greatwqs.iteye.com/blog/2429185
  • 基于Java线程池技术的数据爬虫设计与实现.pdf
  • Java线程池设计与实现

    千次阅读 2017-01-17 14:38:36
    权声明:本文为博主原创文章,未经博主允许不得转载。 ...1 设计思路 ...多线程技术主要是针对CPU解决高效执行任务...如果在服务器上创建线程和销毁线程的时间之和大于线程的执行时间,那么就可以考虑采用线程池。 

    目录(?)[+]

    1 设计思路

    多线程技术主要是针对CPU解决高效执行任务的问题,使用多线程技术可以增加CPU的并行处理能力,但是在服务器上创建线程和销毁线程却是比较花费时间的,而线程的执行时间取决于任务的本身。如果在服务器上创建线程和销毁线程的时间之和大于线程的执行时间,那么就可以考虑采用线程池。 
    线程池这种技术及时为了解决减少线程的创建时间和销毁时间,在客户端的任务请求来到之前,服务器已经创建好了多个线程并把它放在线程池里以供客户端的任务使用,从而提高服务器端的性能。为了达到这种目的,实现线程池主要包括以下4个基本组成部分:

    1)线程池管理类

    主要用于实现创建线程和添加客户端请求的新任务,执行任务以及如何回收已经执行完任务的线程。

    2)工作线程类

    线程池中的线程,它主要用于处理任务队列中的任务。

    3)任务类

    定义任务的各种属性,以及要完成的操作

    4)任务队列

    按先来先服务的顺序用于存放新加入的任务,以便让工作线程来执行

    2 任务队列的实现

    任务队列用来存放要处理的任务,它使用了一个集合类,但是集合本质上是非多线程安全的,通常的类Map、Set以及List都不是线程安全的,当多个线程与集合进行数据交互时,为了使多线程安全,必须采取适当的措施,在文中通过Collections.synchronizedList将其转换为一个线程安全的类。任务队列定义如下所示:

    private List<Task> taskQueue = Collections.synchronizedList(new LinkedList<Task>());
    

    3 任务类的实现

    任务类(Task)其实就是一个线程类,它实现了Runnable接口,在run()方法里面可以定义任务要完成的操作。主要代码如下:

    public class Task implements Runnable{
            @override
            public void run(){
            // 定义任务的操作
            }
    }
    

    4 工作线程类的实现

    工作线程类也是一个线程类,它也实现了Runnable接口,在run()方法里面它首先判断任务队列里面是否有任务,如果没有就等待新任务加入,如果有任务就从任务队列中取出任务并执行,在线程池中可以设定工作线程的个数。在run()方法中的主要代码如下:

    while(isRunning){
        lock.lock();
        while(taskQueue.isEmpty()){
            try{
                taskQueue.wait();
            }catch(Exception e){
            }
        }
        task = (Task)taskQueue.remove(0);
        try{
            new Thread(task).start();
        }catch(Exception e){
            e.printStackTrace();
        }
        lock.unlock();
    }
    

    5 线程池管理类的实现

    线程池管理类的实现采用了单例设计模式,单例设计模式是一种常用的软件设计模式。提供了对唯一实例的访问方式。通过单例设计模式可以保证系统中一个类只有一个实例被外界访问,对于线程池来说,单例设计模式是最好的实现。在线程池管理类中主要有增加任务的方法(addTask)、批量增加任务的方法(batchAddTask)、得到实例的方法(getInstanse)以及执行任务的方法(execute),主要代码如下:

    //增加任务的方法
    public void addTask(Task task){
        lock.lock();
        taskQueue.add(task);
        taskQueue.notifyAll();
        lock.unlock();
    }
    //执行任务的方法
    public void execute(){
        for(int i=0; i<workThreads.length; i++){
            WorkThread wt = workThreads[i];
            if(wt.isWaiting()){
                new Thread(wt).start();
                break;
            }
        }
    }
    

    6 结语

    通过上面的介绍,可以很容易把线程池应用在服务器对客户端任务的管理,通过运用线程池,可以提高线程资源的使用率,从而提高系统的效率。

    展开全文
  • Java线程池详细介绍与使用

    千次阅读 2021-10-02 13:30:29
    文章目录前言一、线程池基础1、什么是线程池2、为什么使用线程池3、线程池有那些优势二、线程池使用1、Java内置线程池:ThreadPoolExecutor2、通过Executor工厂类中的静态方法获取线程池对象第一种、通过...


    前言

    该篇关于多线程中的线程池是我在上篇Java基础没有写到的,当时想把整个多线程直接放在JavaSE中去,但发现网上很多讲Java课程的视频中讲多线程都没有讲到线程池,有些可能会说到,但比较少,可能只会介绍一种如何创建线程池的方式和使用,并没有详细说线程池,所以还是决定单独写一篇关于线程池的就好。而关于多线程的基础知识可以看我之前写的一篇文章,里面不仅有多线程的详细介绍和使用,还有很多的Java基础知识:JavaEE超详细介绍。最后会有一个关于多线程的综合案例,感兴趣的小伙伴有时间可以练一下

    一、线程池基础

    1、什么是线程池

    用一句话来概述就是:线程池是指在初始化一个多线程应用程序过程中创建一个线程集合,然后再需要执行新的任务时重用这些线程而不是新建线程。

    2、为什么使用线程池

    使用线程池最大的原因就是可以根据系统的需求和硬件环境灵活的控制线程的数量,且可以对所有线程进行统一的管理和控制,从而提高系统的运行效率,降低系统的运行压力。

    3、线程池有那些优势

    • 降低资源消耗:线程和任务分离,提高线程重用性
    • 控制线程并发数量,降低服务器压力,统一管理所有线程
    • 提高系统响应速度。假如创建线程用的时间为T1,执行任务的时间为T2,销毁线程的时间为T3,那么使用线程池就免去了T1和T3的时间。

    二、线程池使用

    1、Java内置线程池:ThreadPoolExecutor

     public ThreadPoolExecutor(int corePoolSize,
                               int maximumPoolSize,
                               long keepAliveTime,
                               TimeUnit unit,
                               BlockingQueue<Runnable> workQueue,
                               RejectedExecutionHandler handler) 
    
    • corePoolSize:线程池核心线程数量
    • maximumPoolSize:线程池最大线程数量
    • keepAliverTime:当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间
    • unit:存活时间的单位
    • workQueue:存放任务的队列
    • handler:超出线程范围和队列容量的任务的处理程序

    在这里插入图片描述

    2、通过Executor工厂类中的静态方法获取线程池对象

    通过Executor工厂类获取线程池有三种方式,这三种方式都是通过Executors类中的静态方法来获取的。如下:
    在这里插入图片描述

    第一种、通过newCachedThreadPool获取线程池对象

    该方式特点是:创建一个默认的线程池对象,里面的线程可重用,且在第一次使用时才创建

    package com.itheima.demo02;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadFactory;
    
    /**
     * 练习ExecuTors获取ExecutorService,然后调用方法,提交任务
     *
     * @author Eric
     * @create 2021-10-01 13:33
     */
    public class MyTest1 {
        public static void main(String[] args) {
            //test1();
            test2();
        }
    
        //练习newCachedThreadPool方法
        private static void test1() {
            //1.使用工厂类获取线程池对象
            ExecutorService es = Executors.newCachedThreadPool();
            //2.提交任务
            for (int i = 1; i <= 10; i++) {
                es.submit(new MyRunnable(i));
            }
        }
        //练习newCachedThreadPool(ThreadFactory threadFactory)方法
        private static void test2() {
            //1.使用工厂类获取线程池对象
            ExecutorService es = Executors.newCachedThreadPool(new ThreadFactory() {
                int n = 1;
                @Override
                public Thread newThread(Runnable r) {
                    return new Thread(r,"自定义的线程名称" + n++);
                }
            });
            //2.提交任务
            for (int i = 1; i <= 10; i++) {
                es.submit(new MyRunnable(i));
            }
        }
    }
    
    /**
     * 任务类,包含一个任务编号,在任务中打印出是那一个线程正在执行任务
     */
    class MyRunnable implements Runnable{
        private int id;
        public MyRunnable(int id) {
            this.id = id;
        }
    
        @Override
        public void run() {
            //获取线程的名称,打印一句话
            String name = Thread.currentThread().getName();
            System.out.println(name + "执行了任务" + id);
        }
    }
    

    第二种、通过newFixedThreadPool获取线程池对象

    该方式特点是:可指定创建线程数,并且可以重复用

    package com.itheima.demo02;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadFactory;
    
    /**
     * 练习ExecuTors获取ExecutorService,然后调用方法,提交任务
     *
     * @author Eric
     * @create 2021-10-01 13:33
     */
    public class MyTest2 {
        public static void main(String[] args) {
            //test1();
            test2();
        }
    
        //练习newFixedThreadPool方法
        private static void test1() {
            //1.使用工厂类获取线程池对象
            ExecutorService es = Executors.newFixedThreadPool(3);
            //2.提交任务
            for (int i = 1; i <= 10; i++) {
                es.submit(new MyRunnable2(i));
            }
        }
        private static void test2() {
            //1.使用工厂类获取线程池对象
            ExecutorService es = Executors.newFixedThreadPool(3,new ThreadFactory() {
                int n = 1;
                @Override
                public Thread newThread(Runnable r) {
                    return new Thread(r,"自定义的线程名称" + n++);
                }
            });
            //2.提交任务
            for (int i = 1; i <= 10; i++) {
                es.submit(new MyRunnable2(i));
            }
        }
    }
    
    /**
     * 任务类,包含一个任务编号,在任务中打印出是那一个线程正在执行任务
     */
    class MyRunnable2 implements Runnable{
        private int id;
        public MyRunnable2(int id) {
            this.id = id;
        }
    
        @Override
        public void run() {
            //获取线程的名称,打印一句话
            String name = Thread.currentThread().getName();
            System.out.println(name + "执行了任务" + id);
        }
    }
    

    第三种、通过newSingleThreadExecutor获取线程池对象

    该方式特点是:只会创建一个线程

    package com.itheima.demo02;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadFactory;
    
    /**
     * 练习ExecuTors获取ExecutorService,然后调用方法,提交任务
     *
     * @author Eric
     * @create 2021-10-01 13:33
     */
    public class MyTest3 {
        public static void main(String[] args) {
            //test1();
            test2();
    
        }
    
        //练习newSingleThreadExecutor方法
        private static void test1() {
            //1.使用工厂类获取线程池对象
            ExecutorService es = Executors.newSingleThreadExecutor();
            //2.提交任务
            for (int i = 1; i <= 10; i++) {
                es.submit(new MyRunnable3(i));
            }
        }
        private static void test2() {
            //1.使用工厂类获取线程池对象
            ExecutorService es = Executors.newSingleThreadExecutor(new ThreadFactory() {
                int n = 1;
                @Override
                public Thread newThread(Runnable r) {
                    return new Thread(r,"自定义的线程名称" + n++);
                }
            });
            //2.提交任务
            for (int i = 1; i <= 10; i++) {
                es.submit(new MyRunnable3(i));
            }
        }
    }
    
    /**
     * 任务类,包含一个任务编号,在任务中打印出是那一个线程正在执行任务
     */
    class MyRunnable3 implements Runnable{
        private int id;
        public MyRunnable3(int id) {
            this.id = id;
        }
    
        @Override
        public void run() {
            //获取线程的名称,打印一句话
            String name = Thread.currentThread().getName();
            System.out.println(name + "执行了任务" + id);
        }
    }
    

    关闭线程方法:shutdown和shutdownNow的区别

    • shutdown():仅仅是不再接受新的任务,以前的任务还会继续执行
    • shutdownNow():立刻关闭线程池,如果线程池中还有缓存的任务没有执行,则取消执行,并返回这些任务

    具体代码如下:

    package com.itheima.demo02;
    
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadFactory;
    
    /**
     * 练习ExecuTors获取ExecutorService,然后调用方法,提交任务
     *
     * @author Eric
     * @create 2021-10-01 13:33
     */
    public class MyTest4 {
        public static void main(String[] args) {
            //test1();
            test2();
    
        }
    
        //练习newSingleThreadExecutor方法
        private static void test1() {
            //1.使用工厂类获取线程池对象
            ExecutorService es = Executors.newSingleThreadExecutor();
            //2.提交任务
            for (int i = 1; i <= 10; i++) {
                es.submit(new MyRunnable4(i));
            }
    
            //3.关闭线程池,仅仅是不再接受新的任务,以前的任务还会继续执行
            es.shutdown();
    
            //演示:看能不能继续接收新任务
            //es.submit(new MyRunnable4(888));//不能再提交新的任务了,不然报异常
        }
        private static void test2() {
            //1.使用工厂类获取线程池对象
            ExecutorService es = Executors.newSingleThreadExecutor(new ThreadFactory() {
                int n = 1;
                @Override
                public Thread newThread(Runnable r) {
                    return new Thread(r,"自定义的线程名称" + n++);
                }
            });
            //2.提交任务
            for (int i = 1; i <= 10; i++) {
                es.submit(new MyRunnable4(i));
            }
    
            //3.立刻关闭线程池,如果线程池中还有缓存的任务没有执行,则取消执行,并返回这些任务
            List<Runnable> list = es.shutdownNow();
            System.out.println(list.toString());
        }
    }
    
    /**
     * 任务类,包含一个任务编号,在任务中打印出是那一个线程正在执行任务
     */
    class MyRunnable4 implements Runnable{
        private int id;
        public MyRunnable4(int id) {
            this.id = id;
        }
    
        @Override
        public void run() {
            //获取线程的名称,打印一句话
            String name = Thread.currentThread().getName();
            System.out.println(name + "执行了任务" + id);
        }
    
        @Override
        public String toString() {
            return "MyRunnable4{" +
                    "id=" + id +
                    '}';
        }
    }
    

    三种创建线程池的区别

    第一种:newCachedThreadPool:线程的数据是不做限制的,每次有任务来的时候都会以任务优先,性能最大化(也就是服务器压力比较大)

    第二种:newFixedThreadPool:可以让压力不那么大,并且可以规定线程的数量,当线程的数量达到指定数量的时候,这个时候就不会再有新的线程了

    第三种:newSingleThreadExecutor:绝对的安全,不考虑性能,因为是单线程,永远只有一个线程来执行任务。

    3、Java内置线程池-子接口:ScheduledExecutorService

    当你想控制线程池延迟执行或者重复执行,那么上面创建线程池的三种方式已经不能满足了,这个时候就需要用到我们的线程池的子接口:ScheduledExecutorService

    ScheduledExecutorService介绍如下:
    在这里插入图片描述
    通过该子接口中方法来达到我们的需求:
    在这里插入图片描述

    方法一:通过schedule()延迟执行任务

    具体代码如下:

    package com.itheima.demo03;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    /**
     * 测试ScheduleExecutorService接口中的延迟执行任务和重复执行任务的功能
     *
     * @author Eric
     * @create 2021-10-02 9:17
     */
    public class ScheduleExecutorServiceDemo01 {
        public static void main(String[] args) {
            //1.获取一个具备延迟执行任务的线程池对象
            ScheduledExecutorService es = Executors.newScheduledThreadPool(3);
            //2.创建多个任务对象,提交任务,每个任务延迟2秒执行
            es.schedule(new MyRunnable(1),2, TimeUnit.SECONDS);
            System.out.println("over");
        }
    }
    
    class MyRunnable implements Runnable{
        private int id;
    
        public MyRunnable(int id) {
            this.id = id;
        }
    
        @Override
        public void run() {
            String name = Thread.currentThread().getName();
            System.out.println(name + "执行了任务:" + id);
        }
    }
    

    方法二:通过scheduleAtFixedRate()方法延迟执行任务

    具体代码如下:

    package com.itheima.demo03;
    
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.ThreadFactory;
    import java.util.concurrent.TimeUnit;
    
    /**
     * 测试ScheduleExecutorService接口中的延迟执行任务和重复执行任务的功能
     *
     * @author Eric
     * @create 2021-10-02 9:17
     */
    public class ScheduleExecutorServiceDemo02 {
        public static void main(String[] args) {
            //1.获取一个具备延迟执行任务的线程池对象
            ScheduledExecutorService es = Executors.newScheduledThreadPool(3, new ThreadFactory() {
                int n = 1;
                @Override
                public Thread newThread(Runnable r) {
                    return new Thread(r,"自定义线程名称:" + n++);
                }
            });
            //2.创建多个任务对象,提交任务,每个任务延迟2秒执行        //初始等待1秒,执行任务间隔2秒
            es.scheduleAtFixedRate(new MyRunnable2(1),1,2,TimeUnit.SECONDS);
            System.out.println("over");
    
        }
    }
    
    class MyRunnable2 implements Runnable{
        private int id;
    
        public MyRunnable2(int id) {
            this.id = id;
        }
    
        @Override
        public void run() {
            String name = Thread.currentThread().getName();
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name + "执行了任务:" + id);
        }
    }
    

    方法三:通过scheduleWithFixedDelay()方法延迟执行任务

    package com.itheima.demo03;
    
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.ThreadFactory;
    import java.util.concurrent.TimeUnit;
    
    /**
     * 测试ScheduleExecutorService接口中的延迟执行任务和重复执行任务的功能
     *
     * @author Eric
     * @create 2021-10-02 9:17
     */
    public class ScheduleExecutorServiceDemo03 {
        public static void main(String[] args) {
            //1.获取一个具备延迟执行任务的线程池对象
            ScheduledExecutorService es = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
                int n = 1;
                @Override
                public Thread newThread(Runnable r) {
                    return new Thread(r,"自定义线程名称:" + n++);
                }
            });
            //2.创建多个任务对象,提交任务,每个任务延迟2秒执行        //初始延迟1秒,执行任务间隔2秒(任务执行时间不计入的,是等任务执行之后再间隔2秒)
            es.scheduleWithFixedDelay(new MyRunnable3(1),1,2,TimeUnit.SECONDS);
            System.out.println("over");
    
        }
    }
    
    class MyRunnable3 implements Runnable{
        private int id;
    
        public MyRunnable3(int id) {
            this.id = id;
        }
    
        @Override
        public void run() {
            String name = Thread.currentThread().getName();
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name + "执行了任务:" + id);
        }
    }
    

    ScheduleExecutorService中三个方法的小结

    1、设置延迟多长时间任务执行,可以使用schedule()方法
    在这里插入图片描述
    2、设置每间隔多长时间执行,有两种方式:
    方式一:只计算第一次开始到第二次开始的间隔时间

    在这里插入图片描述
    方式二:第一次任务结束之后开始计时,间隔多长时间,到第二次任务开始之前,这个时间段。
    在这里插入图片描述

    4、异步计算结果(Future)

    介绍如下:
    在这里插入图片描述

    具体操作代码如下:

    package com.itheima.demo04;
    
    import java.util.concurrent.*;
    
    /**
     * 练习异步计算结果
     *
     * @author Eric
     * @create 2021-10-02 10:30
     */
    public class FutureDemo {
        public static void main(String[] args) throws Exception {
            //1.获取线程池对象
            ExecutorService es = Executors.newCachedThreadPool();
            //2.创建Callable类型对象
            Future<Integer> f = es.submit(new MyCall(1, 1));
            //3.判断任务是否已经完成
            //test1(f);
    
            //测试get()方法
            //boolean b = f.cancel(true);
            //System.out.println("取消任务执行的结果:" + b);
    
            //Integer v = f.get(1, TimeUnit.SECONDS);//由于等待时间过短,任务来不及执行完成,所以会报异常
            //System.out.println("任务执行的结果是:"  +v);
        }
    
        //正常执行流程
        private static void test1(Future<Integer> f) throws Exception {
            boolean done = f.isDone();
            System.out.println("第一次判断任务是否完成:" + done);
    
            boolean cancelled = f.isCancelled();
            System.out.println("第一次判断任务是否取消:" + cancelled);
    
            Integer v = f.get();//一直等待任务的执行,直到完成
            System.out.println("任务执行的结果是:"  + v);
    
            //再一次判断任务是否完成
            boolean done2 = f.isDone();
            System.out.println("第二次判断任务是否完成:" + done2);
    
            boolean cancelled2 = f.isCancelled();
            System.out.println("第二次判断任务是否取消:" + cancelled2);
        }
    }
    
    
    class MyCall implements Callable<Integer>{
        private int a;
        private int b;
    
        //通过构造方法传递两个参数
        public MyCall(int a, int b) {
            this.a = a;
            this.b = b;
        }
    
        @Override
        public Integer call() throws Exception {
            String name = Thread.currentThread().getName();
            System.out.println(name + "准备开始计算...");
            Thread.sleep(2000);
            System.out.println(name + "计算完成...");
            return a + b;
        }
    }
    

    三、线程池综合案例

    最后,拿一个综合案例来结合前面写的融合一下,感兴趣的小伙伴可以锻炼一下。
    在这里插入图片描述

    具体代码如下:
             任务类代码:

    package com.itheima.demo05;
    
    /**
     * 任务类:
     *      包含了商品数量,客户名称,送手机的行为
     *
     * @author Eric
     * @create 2021-10-02 10:46
     */
    public class MyTask implements Runnable{
        //设计一个变量,用于表示商品的数量
        private static int id = 10;
        //表示客户名称变量
        private String userName;
    
        public MyTask(String userName) {
            this.userName = userName;
        }
    
        @Override
        public void run() {
            String name = Thread.currentThread().getName();
            System.out.println(userName + "正在使用" + name + "参与秒杀任务...");
    
            try {
                Thread.sleep(200);//为了逼真一点,休眠200毫秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            synchronized (MyTask.class){
                if(id > 0){
                    System.out.println(userName + "使用" + name + "秒杀:" + id-- + "号商品成功啦!");
                }else {
                    System.out.println(userName + "使用" + name + "秒杀失败了!");
                }
            }
        }
    }
    

             测试类代码:

    package com.itheima.demo05;
    
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    /**
     * 主程序类,测试任务类
     *
     * @author Eric
     * @create 2021-10-02 10:50
     */
    public class MyTest {
        public static void main(String[] args) {
            //1.创建一个线程池对象
            ThreadPoolExecutor pool = new ThreadPoolExecutor(3,5,1, TimeUnit.MINUTES,new LinkedBlockingQueue<>(15));
            //2.循环创建任务对象
            for (int i = 0; i < 20; i++) {
                MyTask myTask = new MyTask("客户" + i);
                pool.submit(myTask);
            }
            //3.关闭线程池
            pool.shutdown();
        }
    }
    

    PS

    这些知识点都是我在B站看黑马的线程池视频得来的,讲的很详细。个人对线程池也有一个比较全的认识,感兴趣的小伙伴有时间可以去看一遍视频:黑马线程池详细讲解视频路劲。当然,这不是广告,只是

    展开全文
  • Java线程池详解

    2021-05-30 17:06:52
    线程池(Thread Pool)是一种基于池化思想管理线程的工具,经常出现在多线程服务器中,如MySQL。 线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,同时也降低了计算机的整体性能。...
  • 首先我们要先知道 Java 中创建线程池的方式,java中创建线程池的方式一般有两种,如下所示: 通过Executors工厂方法创建 通过newThreadPoolExecutor(intcorePoolSize, intmaximumPoolSize, ...
  • java线程池案例

    2022-03-03 16:34:02
    线程Thread是一个重量级资源,线程的创建、启动以及销毁都是比较耗费系统资源的,同时受限于系统资源的限制,线程的数量与系统性能是一种抛物线的关系,因此对线程的管理,是一种非常好的程序设计习惯,自JDK1.5起,...
  • Java线程池底层原理

    2021-12-16 16:25:27
    下面三种线程池底层都是调用的ThreadpoolExecutor这个方法,ThreadpoolExecutor()构造方法包含七大参数,想要了解线程池底层原理,必须掌握这七大参数的含义 Executors.newFixedThreadPool(int) Executors....
  • 基于这样的设计理念,在Java中,线程方法的异常都应该在线程代码边界之内(run方法内)进行处理。换句话说,我们不能捕获从线程中逃逸的异常。 JDK如何控制线程异常不会跑到外部线程? 通过java.lang.Runnable.run()...
  • 【Java线程高频】- java线程池怎么做到复用的? 首先来看下线程池的执行线程的流程: 首先会先判断线程池的状态,即是否在运行状态,若线程为非运行状态 ,则会拒绝; 接下来会去判断线程数是否小于核心线程数,若...
  • java线程池工作原理

    2022-01-03 23:36:32
    线程池执行流程
  • 为什么要使用线程池 首先线程的创建和销毁需要调用操作系统内核的API,然后操作系统为其分配一系列资源,整个成本很高,也就导致线程是一个重量级对象。其次如果并发线程数量很多,并且每个线程执行一个很短的任务...
  • Java线程池详细解释

    千次阅读 2021-02-28 13:40:49
    第一章 线程池方式1.1线程池的思想我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:如果并发的线程数量很多,并且每个线程都是执行一个...在Java中可以通过线程池来达到这样的效果...
  • Java线程池Executor详解

    2021-12-12 22:12:25
    线程池类图 我们最常使用的Executors实现创建线程池使用线程主要是用上述类图中提供的类。在上边的类图中,包含了一个Executor框架,它是一个根据一组执行策略的调用调度执行和控制异步任务的框架,目的是提供一种将...
  • Java线程池体系

    2021-12-28 19:18:55
    一、线程池的整体类图 (实线是继承 虚线是实现) ...4.AbstractExecutorService:抽象类,运用模板方法设计模式实现了一部分方法 5.ThreadPoolExecutor:普通线程池类,包含最基本的一些线程池
  • Java线程池ThreadPool详解1. 线程池概述1.1 线程池简介1.2 线程池特点1.3 线程池解决的问题2. 线程池原理分析2.1 线程池总体设计2.6 线程池流转状态2.2 线程池执行流程2.3 线程池核心参数2.4 线程池饱和策略2.5 ...
  • 线程池的接口为java.util.concurrent.ExecutorService,里面的方法行为约定如下: void shutdown() 发起一个有序的停止,先前已经提交的任务会被执行,并拒绝提交新的任务。 重复调用shutdown不会有副作用,遵从幂...
  • Java线程池应用

    2021-03-12 21:51:00
    Java中,多线程有着广泛运用。在实际应用中,好的软件设计不建议手动创建和销毁线程。线程的创建和销毁是非常耗 CPU 和内存资源的,因为这需要 JVM 和操作系统的参与。为此,我们在面临多线程问题时,通常会采用...
  • 本文实例讲述了Java线程池用法。分享给大家供大家参考,具体如下:一 使用newSingleThreadExecutor创建一个只包含一个线程的线程池1 代码import java.util.concurrent.*;public class executorDemo{public static ...
  • 深度解读 java 线程池设计思想及源码实现转自https://javadoop.com/2017/09/05/java-thread-pool/hmsr=toutiao.io&amp;utm_medium=toutiao.io&amp;utm_source=toutiao.io我相信大家都看过很多的关于线程池的...
  • Excutors JDK1.5提供的线程池工具类
  • Java线程池 - (一)自定义线程池 什么是线程池? 线程池就是一种多线程处理形式,处理过程中可以将任务添加到队列中,然后在创建线程后自动启动这些任务 为什么要使用线程池? 可以根据系统的需求和硬件环境灵活的...
  • Java线程池拒绝策略

    2021-02-27 08:46:41
    Java提供的策略实现CallerRunsPolicypublic static class CallerRunsPolicy implements RejectedExecutionHandler {public CallerRunsPolicy() { }public void rejectedExecution(Runnable r, ThreadPoolExecutor e)...
  • 打开今日头条,查看更多精彩图片本文属于对Java线程池的综合思考,如果您对Java线程池还不太了解,可以先收藏。本文讲解如下几个内容:当核心线程满时,先创建临时线程还是先加入队列?临时线程工作时间和方式?核心...
  • Java 线程池原理

    2021-08-26 18:11:59
    本文开篇简述了线程池概念和用途,接着结合线程池的源码,帮助大家领略线程池设计思路,最后回归实践,通过案例讲述使用线程池遇到的问题,并给出了一种动态化线程池解决方案。 1.1 线程池是什么 线程池(Thread
  • java线程池介绍及应用案例

    千次阅读 2019-01-25 18:54:25
    线程Thread是一个重量级资源,线程的创建、启动以及销毁都是比较耗费系统资源的,同时受限于系统资源的限制,线程的数量与系统性能是一种抛物线的关系,因此对线程的管理,是一种非常好的程序设计习惯,自JDK1.5起,...
  • Java线程池面试要点

    2021-12-31 19:26:56
    ava线程池在面试的时候问的挺多的,曾经我就在面试过程中两次被问到,面试官通过面试者对线程池的理解回答也能大致了解到面试者的实际开发经验如何,以及对多线程的理解运用有没有深入到位。 同时,面试官在切入多...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 122,885
精华内容 49,154
关键字:

java线程池设计

java 订阅