精华内容
下载资源
问答
  • 一 基本信息 首先,从Executor接口开始 查看注释 An object that executes ...一个执行“”提交的任务“”的对象 * This interface provides a way of decoupling task submission from the * mechanics of how ...

    一 基本信息

    首先,从Executor接口开始

    查看注释

    An object that executes submitted {@link Runnable} tasks.

    一个执行“”提交的任务“”的对象

    * This interface provides a way of decoupling task submission from the
     * mechanics of how each task will be run, including details of thread
     * use, scheduling, etc.

    这个接口提供了一种把 任务提交任务如何运行的机制(包括线程使用,调度等)

    解耦方式。

    An {@code Executor} is normally used
     * instead of explicitly creating threads. 

    通常会使用Executor而不是使用Thread

    二 类,接口 ,继承和实现关系

    Executor 接口有一个子接口ExecutorService

    继续下分是AbstractExecutorService然后是

    ThreadPoolExecutor

     

    三.实现线程顺序执行

        Thread a = new Thread() {
                public void run() {
        
            System.out.println("thread a 执行");
                  }
            };
            Thread b = new Thread() {
                public void run() {
                    
                    System.out.println("thread b 执行");
                }
            };
            Thread c = new Thread() {
                public void run() {
                    
                    System.out.println("thread c 执行");
                }
            };
            Thread d = new Thread() {
                public void run() {
                    
                    System.out.println("thread d 执行");
                }
            };
            Thread e = new Thread() {
                public void run() {
                    
                    System.out.println("thread e 执行");
                }
            };
        
            
            ExecutorService service = Executors.newSingleThreadExecutor();
            service.execute(a);
            service.execute(b);
            service.execute(c);
            service.execute(d);
            service.execute(e);

     

     

     

     

     

    展开全文
  • 不过,就算队列里面有任务,线程池也不会马上执行它们。 当调用 execute() 方法添加一个任务时,线程池会做如下判断: 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务; 如果正在运行...

    1、线程池的工作原理?

    1. 线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过,就算队列里面有任务,线程池也不会马上执行它们。
    2. 当调用 execute() 方法添加一个任务时,线程池会做如下判断:
      1. 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
      2. 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列。
      3. 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建线程运行这个任务;
      4. 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常,告诉调用者“我不能再接受任务了”。

     

    1. 当一个线程完成任务时,它会从队列中取下一个任务来执行。
    2. 当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。

    这样的过程说明,并不是先加入任务就一定会先执行。假设队列大小为 10,corePoolSize 为 3,maximumPoolSize 为 6,那么当加入 20 个任务时,执行的顺序就是这样的:首先执行任务 1、2、3,然后任务 4~13 被放入队列。这时候队列满了,任务 14、15、16 会被马上执行,而任务 17~20 则会抛出异常。最终顺序是:1、2、3、14、15、16、4、5、6、7、8、9、10、11、12、13。

    2、线程池有哪些配置项?

    线程池可以使用java.util.concurrent.ThreadPoolExecutor来创建,在该类中包含最全参数的构造函数如下:

    public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

    相应的入参就是线程池可以配置的参数:

    相应的入参就是线程池可以配置的参数:

    • corePoolSize :核心池的大小,如果调用了prestartAllCoreThreads()或者prestartCoreThread()方法,会直接预先创建corePoolSize的线程,否则当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;这样做的好处是,如果任务量很小,那么甚至就不需要缓存任务,corePoolSize的线程就可以应对;
    • maximumPoolSize:线程池最大线程数,表示在线程池中最多能创建多少个线程,如果运行中的线程超过了这个数字,那么相当于线程池已满,新来的任务会使用RejectedExecutionHandler 进行处理;
    • keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止,然后线程池的数目维持在corePoolSize 大小;
    • unit:参数keepAliveTime的时间单位;
    • workQueue:一个阻塞队列,用来存储等待执行的任务,如果当前对线程的需求超过了corePoolSize大小,才会放在这里;
    • threadFactory:线程工厂,主要用来创建线程,比如可以指定线程的名字;
    • handler:如果线程池已满,新的任务的处理方式

    3、怎样优化线程池的配置?

    如何合理配置线程池大小,仅供参考。

    一般需要根据任务的类型来配置线程池大小:

    如果是CPU密集型任务,就需要尽量压榨CPU,参考值可以设为 NCPU+1

    如果是IO密集型任务,参考值可以设置为2*NCPU

    当然,这只是一个参考值,具体的设置还需要根据实际情况进行调整,比如可以先将线程池大小设置为参考值,

    再观察任务运行情况和系统负载、资源利用率来进行适当调整。

    其中NCPU的指的是CPU的核心数,可以使用Runtime.getRuntime().availableProcessors()来获取;

    展开全文
  • 线程池 顺序执行线程

    千次阅读 2019-07-31 18:14:37
    使用线程池批量顺序执行任务 AtomicInteger、CountDownLatch、ThreadPoolExecutor组合使用 import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import java.util.List; import java.util.Map; ...

    使用线程池批量顺序执行任务
    AtomicInteger、CountDownLatch、ThreadPoolExecutor组合使用

    import com.alibaba.fastjson.JSON;
    import lombok.extern.slf4j.Slf4j;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.atomic.AtomicInteger;
    
    @Slf4j
    public class ThreadPollUtil {
    
        /**
         * @param paramList 任务参数列表
         * @param process   要执行的功能
         * @param threadNum 线程数
         * @param <P>       参数类型
         * @param <V>       返回值类型
         * @return 返回结果集
         * @throws InterruptedException
         */
        public static <P, V> Map<Integer, V> process(final List<P> paramList, final Process<P, V> process, int threadNum) throws InterruptedException {
            //如果任务数少于线程数取任务为线程个数
            threadNum = Math.min(paramList.size(), threadNum);
            //保证任务是顺序执行的
            final AtomicInteger atomicInteger = new AtomicInteger(0);
            //用于统计已经执行完成的线程
            final CountDownLatch countDownLatch = new CountDownLatch(threadNum);
            //保存任务执行结果
            final ConcurrentHashMap<Integer, V> resultMap = new ConcurrentHashMap<>();
            ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(threadNum);
            threadPool.setMaximumPoolSize(threadNum);
            for (int i = 0; i < threadNum; i++) {
                threadPool.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            while (true) {
                                int index = atomicInteger.getAndAdd(1);
                                if (index >= paramList.size()) {
                                    break;
                                }
                                P param = paramList.get(index);
                                try {
                                    LOG.info("index:{}", index);
                                    V result = process.doTask(param);
                                    if (result != null) {
                                        log.info("index:{} result:{}", index, JSON.toJSONString(result));
                                        resultMap.put(index, result);
                                    }
                                } catch (Exception e) {
                                    log.error("运行失败 param:{}", JSON.toJSONString(param), e);
                                }
                            }
                        } catch (Exception e) {
                            log.error(null, e);
                        } finally {
                            countDownLatch.countDown();
                        }
    
                    }
                });
            }
            try {
                countDownLatch.await();
            } catch (Exception e) {
                log.error(null, e);
            }
            threadPool.shutdown();
            return resultMap;
        }
    
        /**
         * @param <P> 参数类型
         * @param <V> 返回值类型
         */
        public interface Process<P, V> {
            V doTask(P p);
        }
    
    }
    
    展开全文
  • 笔者今天看到一个有趣的面试题,如何让多个线程按照既定的顺序依次执行?比如每个线程输出一个整数, 那么期望就是这样的:0,1,2,3,4,5,6,7,8,9.而不是0,2,4,1,3,5,8,7,9,6 乍一看,这不是反人性...

    笔者今天看到一个有趣的面试题,如何让多个线程按照既定的顺序依次执行?比如每个线程输出一个整数,

    那么期望就是这样的:0,1,2,3,4,5,6,7,8,9.而不是0,2,4,1,3,5,8,7,9,6

    乍一看,这不是反人性的考题吗?多线程本来就以乱序执行出名的。稍加思索,想到3种解决方案,分别用代码实现之。
    方法1: 使用join方法
    代码如下:

    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("t1...");
        }
    });
    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("t2...");
        }
    });
    Thread t3 = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("t3...");
        }
    });
    try {
        t1.start();
        t1.join();
        t2.start();
        t2.join();
        t3.start();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    

    方法2:使用newSingleThreadExecutor

    ExecutorService pool = Executors.newSingleThreadExecutor();
    for (int i = 0; i < 1000; ++i) {
        final int number = i;
        pool.execute(() -> {
            System.out.println("I am " + number);
        });
    }
    pool.shutdown();
    

    方法3:使用ThreadPoolExecutor,设置它的核心线程数为1

    ExecutorService pool = new ThreadPoolExecutor(1, 1000, 300, TimeUnit.SECONDS, new LinkedBlockingQueue(1000), Executors.defaultThreadFactory(), newThreadPoolExecutor.AbortPolicy());
    for (int i = 0; i < 1000; ++i) {
        final int number = i;
    
        pool.execute(() -> {
            System.out.println("I am " + number);
    
        });
    
    }
    pool.shutdown();
    

    各个参数含义如下:

    1、corePoolSize, 核心线程数,建议和cpu的核心数一样,当有任务提交,检测当前线程池内的线程数小于corePoolSize的话,新建线程执行任务,直到达到corePoolSize。线程池内的线程数大于等于corePoolSize时,将任务放入workQueue等待
    2、maximumPoolSize,允许线程池内最大线程数,当队列满了之后,如果线程池内的线程数小于maximumPoolSize新建线程,如果大于等于执行拒绝策略。
    3、keepAliveTime,线程最大空闲时间,如果设置60s,那么线程空闲60s后自动结束。
    unit,时间单位分钟,秒等等。
    4、workQueue,线程数超过corePoolSize存放任务的地方。
    5、threadFactory,线程工厂,默认的即可。
    6、handler,拒绝策略,分4种,AbortPolicy直接抛出异常、DiscardPolicy悄悄抛弃不执行、CallerRunsPolicy(调用者运行):该策略既不会抛弃任务也不会抛出异常,而是将这个任务退回给调用者,从而降低新任务的流量;、DiscardOldestPolicy(抛弃最旧的)

    展开全文
  • 创建一个单线程化的线程池,它只会用唯一的工作线程执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。示例代码如下: ExecutorService newSingleThreadExecutor = Executors....
  • java中线程池ExecutorService 线程管理

    千次阅读 2015-08-06 14:11:43
    java中线程池ExecutorService 线程管理
  • import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.junit.Test; public class MyTest { ... // test1:当线程池中所有的线程执行完毕后,才退出主线程. Ex
  • 线程池线程的选择

    2016-08-04 12:43:00
    能用线程池就用线程池线程池效率比...如果执行线程时间特别长,那手动创建线程,和放入线程池中没太大区别. 线程池非常适合做大量的小的运算。 转载于:https://www.cnblogs.com/yuanjunqq/p/5736252.html...
  • 使用线程池创建线程

    千次阅读 2019-03-10 05:22:26
    重用线程池中线程,避免因为线程的创建和销毁所带来的性能开销. 线程是轻量级的进程,虽然创建和销毁的开销比进程小得多,但仍是一笔不小的开销 能有效控制线程池的最大并发数,避免大量的线程之间因互相抢占...
  • 今天小编就为大家分享一篇python自定义线程池控制线程数量的示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 本文主要围绕一个问题展开:线程执行顺序,比如某个线程在其他线程并发执行完毕后最后执行。join介绍join()是Thread类的一个方法,join()方法的作用是等待这个线程结束。t.join()方法阻塞调用此方法的线程(calling ...
  • 本文转载: ... public class Test {  public static void main(String args[]) throws InterruptedException {  ExecutorService exe = Executors....子线程执行顺序不能控制,所以输出的结果是乱序的。
  • 能用线程池就用线程池线程池效率比线程高很多。 线程池处理线程顺序不一定。 ...如果执行线程时间特别长,那手动创建线程,和放入线程池中没太大区别. 线程池非常适合做大量的小的运算。
  • 线程池执行顺序

    千次阅读 2019-12-11 09:39:08
    线程池提交任务时的执行顺序如下: 向线程池提交任务时,会首先判断线程池中线程数是否大于设置的核心线程数,如果不大于,就创建一个核心线程来执行任务。 如果大于核心线程数,就会判断缓冲队列是否满了,如果...
  • Java线程池线程中断

    千次阅读 2016-01-23 13:15:52
    这是一个统一时间只能执行单个线程的线程池,如果上一个线程还处于执行状态,那么新加进来的线程就会等待直到上一个线程执行完成,利用这点可以实现类似顺序队列一样的功能; - newSingleThreadSc
  • 在使用线程池时,当用线程池执行多个任务时,由于执行的任务时间过长,会导制两个任务互相执行,如果两个任务具有一定的操作顺序,可能会导制不同的操作结果,这时,就要将线程池顺序操作。下面先给一段代码,该...
  • java线程池执行顺序

    2021-06-20 11:17:15
    // thread.java private Runnable target;//targets是runnable接口 //当thread.start()方法调用后,jvm会启动线程并调用run方法---...//注意这里,无论是线程池线程还是其他地方的,在start方法后,jvm都会执行这里
  • Java使用线程池批量顺序执行任务

    千次阅读 2017-09-27 21:35:52
    使用线程池批量顺序执行任务 AtomicInteger、CountDownLatch、ThreadPoolExecutor组合使用package tool.thread;import com.alibaba.fastjson.JSON; import org.slf4j.Logger; import org.slf4j.LoggerFactory;...
  • ThreadPoolExecutor 线程池线程

    千次阅读 2013-12-24 11:07:23
    线程池就是一个线程的容器,每次只执行额定数量的线程。 java.util.concurrent.ThreadPoolExecutor 就是这样的线程池。它很灵活,但使用起来也比较复杂,本文就对其做一个介绍。首先是构造函数。以最简单的构造...
  • 线程池重要参数 线程池执行顺序

    千次阅读 2019-09-10 19:30:07
  • Java并发编程之使用线程池管理线程
  • 线程池线程相关类

    2018-11-22 10:31:54
    线程池在系统启动时即创建大量空闲的线程,程序将一个Runnable对象或Callable对象传给线程池线程池会启动一个线程执行它们的run()或call方法,当方法执行结束后,线程并不会死亡,而是再次返回到线程池成为空闲...
  • 线程面试题和答案:线程锁+线程池+线程同步1、并发编程三要素?2、多线程的价值?3、创建线程的有哪些方式?区别是什么?4、创建线程的三种方式的对比?4、线程的生命周期及五种基本状态及转换条件1、Java线程具有...
  • 理论: 1 Executors 预置 4种线程池: Fixed SingleThread cached ...将Callable对象submit 线程池中,会返回Future对象,然后 可以通过get 获取对应数据,但是会等待 3 ExecutorCompletionService 接收线程队...
  • 控制多线程执行顺序

    千次阅读 2018-11-01 14:30:58
    控制多线程执行顺序 示例代码的码云地址:https://gitee.com/suwenguang/test/blob/master/fuxi/src/main/java/多线程/控制多线程的顺序执行/App.java 多线程是为了同步完成多项任务,不是为了提高运行效率,而是...
  • 大概说下问题(类似),就是新建一个线程池,核心线程是3个,最大线程数是6个,阻塞队列是12,过期时间是20s,假设每个线程处理完一个任务需要1s。如果一次性来了18 个任务,也就是线程全开,队列塞满,那么:3s之后...
  • 线程锁+线程池+线程同步等

    千次阅读 2019-04-28 16:20:39
    1)原子性:原子性指的是一个或者多个操作,要么全部执行并且在执行的过程不被其他操作打断,要么就全部都不执行。 2)可见性:可见性指多个线程操作一个共享变量时,其中一个线程对变量进行修改后,其他线程可以...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 89,411
精华内容 35,764
关键字:

线程池中线程执行顺序