zoukankan      html  css  js  c++  java
  • 多线程(七)JDK原生线程池

    如同数据库连接一样,线程的创建、切换和销毁同样会耗费大量的系统资源。为了复用创建好的线程,减少频繁创建线程的次数,提高线程利用率可以引用线程池技术。使用线程池的优势有如下几点:
            1、保持一定数量的线程,减少了线程频繁创建和销毁资源消耗。
            2、使用线程的时候直接由线程池中取出线程,省去了创建线程的时间,侧面提高了系统的响应时间。
            3、需要使用线程的时候直接从线程池中取出,避免了人为的不合理创建线程,减少了潜在的风险。
    Doug Lea在实现JUC中提供了原生的线程池,并提供了各种线程管理策略来适应于不同的使用场景。使用的时候可通过Executors获取各种线程池实例。

    这里提供了六对12个方法来创建ExecutorService,其中每种类型的ExecutorService可以适用于不同的应用场景,对线程的管理策略也各不相同。下面就看一下各个方法的注释:

    /**
         * Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available.
         * 创建一个线程池,需要的时候会创建新的线程,如果有可用的线程则会复用以前已经创建好的线程。
         * These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks.
         * 这些线程池通常情况下可以提升哪些短期异步任务的性能
         * Calls to {@code execute} will reuse previously constructed threads if available.
         * 如果以创建的线程状态可用的话,调用execute可以复用他们
         * If no existing thread is available, a new thread will be created and added to the pool.
         * 如果不存在可用状态的线程,那么将会创建一个新线程同时会把该线程添加到线程池中
         * Threads that have not been used for sixty seconds are terminated and removed from the cache.
         *那些超过60s没用的线程将会被销毁同时从缓存中移除
         * Thus, a pool that remains idle for long enough will not consume any resources.
         *因此长时间空闲的线程池不会消耗任何资源
         * Note that pools with similar properties but different details (for example, timeout parameters) may be created using {@link ThreadPoolExecutor} constructors.
         *可以使用ThreadPoolExecutor创建性质相似但实现细节不同的线程池
         * @return the newly created thread pool
         */
    
        public static ExecutorService newCachedThreadPool();
    
        //可以使用自定义的ThreadFactory 类创建线程,其它和无参方法一致
        public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory);
    /**
         * Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue.
         *创建一个可重用、固定数量线程的线程池
         * At any point, at most {@code nThreads} threads will be active processing tasks.
         *任何时间最多只有 nThreads 个线程被激活来执行任务
         * If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available.
         * 当无可用空闲线程的时候,如果有新任务被提交,这些新任务将会一直等待直至有可用线程来执行。
         * If any thread terminates due to a failure during execution  prior to shutdown, a new one will take its place if needed to execute subsequent tasks.
         *如果任何线程正常关闭之前在执行过程中因失败而提前终止,那么如果有未被执行的后续任务,则会创建新的线程来继续执行。
         * The threads in the pool will exist  until it is explicitly {@link ExecutorService#shutdown shutdown}.
         * 线程池中的所有线程在明确掉用shutdown之后将会退出
         *
         * @param nThreads the number of threads in the pool
         * @return the newly created thread pool
         * @throws IllegalArgumentException if {@code nThreads <= 0}
         */
        public static ExecutorService newFixedThreadPool(int nThreads);
        //可自定义ThreadFactory
        public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory);
    /**
         * Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.
         *  创建一个线程池,该线程在延迟指定时间之后可以周期性的执行线程体
         * @param corePoolSize the number of threads to keep in the pool,
         * even if they are idle
         * @return a newly created scheduled thread pool 注意返回值类型是ScheduledExecutorService,不要使用ExecutorService来接收,否则找不到schedule执行方法
         * @throws IllegalArgumentException if {@code corePoolSize < 0}
         */
    
        public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize);
        //可自定义ThreadFactory
        public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory);
    /**
         * Creates an Executor that uses a single worker thread operating off an unbounded queue.
         *创建一个Executor,使用一个线程来工作,该线程存储在LinkedBlockingQueue中
         * (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.)
         *注,如果任何线程正常关闭之前在执行过程中因失败而提前终止,那么如果有未被执行的后续任务,则会创建新的线程来继续执行。
         * Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time.
         *  任务是按顺序执行的,任何时间都只有一个线程来执行任务
         * Unlike the otherwise equivalent {@code newFixedThreadPool(1)} the returned executor is guaranteed not to be reconfigurable to use additional threads.
         *
         * @return the newly created single-threaded Executor
         */
    
        public static ExecutorService newSingleThreadExecutor();
        //可自定义ThreadFactory
        public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory);
    /**
         * Creates a single-threaded executor that can schedule commands
         * to run after a given delay, or to execute periodically.
         * (Note however that if this single
         * thread terminates due to a failure during execution prior to
         * shutdown, a new one will take its place if needed to execute
         * subsequent tasks.)  Tasks are guaranteed to execute
         * sequentially, and no more than one task will be active at any
         * given time. Unlike the otherwise equivalent
         * {@code newScheduledThreadPool(1)} the returned executor is
         * guaranteed not to be reconfigurable to use additional threads.
         * @return the newly created scheduled executor
         */
    
        public static ScheduledExecutorService newSingleThreadScheduledExecutor();
    
        public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory)

     使用示例:

    package thread.blogs.threadpool;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadFactory;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * Created by PerkinsZhu on 2017/8/31 13:59.
     */
    public class PoolTest {
    
        public static void main(String[] args) {
    //        testCachedThreadPool();
    //        testSingleThreadExecutor();
    //        testFixedThreadPool();
            testScheduledThreadPool();
        }
        private static ThreadFactory myFactory = new MyThreadFactory();
    
        private static void testSingleThreadExecutor() {
            //一个一个的依次执行
            doHandle(Executors.newSingleThreadExecutor(myFactory));
        }
    
        private static void testFixedThreadPool() {
            //两个两个的一起执行
            doHandle(Executors.newFixedThreadPool(2,myFactory));
        }
    
        private static void testCachedThreadPool() {
            //10个一起一次性执行完
            doHandle(Executors.newCachedThreadPool(myFactory));
        }
    
        private static void testScheduledThreadPool() {
            //定时周期执行
            Executors.newScheduledThreadPool(1,myFactory).scheduleAtFixedRate(runnable, 500, 2000, TimeUnit.MILLISECONDS);
        }
    
        private static Runnable runnable = () -> {
            sleep(1000);
            System.out.println(Thread.currentThread().getName() + "    work!!!");
        };
    
    
        private static void doHandle(ExecutorService executorService) {
            for (int i = 0; i < 10; i++) {
                executorService.execute(runnable);
            }
            executorService.shutdown();
        }
    
        private static void sleep(int time) {
            try {
                Thread.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    class MyThreadFactory implements ThreadFactory {//自定义ThreadFactory
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;
    
        MyThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            namePrefix = "☆☆☆--" + poolNumber.getAndIncrement() + "-****-";
        }
    
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
            if (t.isDaemon()) {
                t.setDaemon(false);
            }
            if (t.getPriority() != Thread.NORM_PRIORITY) {
                t.setPriority(Thread.NORM_PRIORITY);
            }
            return t;
        }
    
    }

     在使用的时候必须明白各种线程池是否适用于自己的情景,选取合适的线程池进行使用。

    =========================================

    原文链接:多线程(七)JDK原生线程池转载请注明出处!

    =========================================

    ---end

  • 相关阅读:
    Struts1防止重复提交
    Jquery真的不难
    原生Ajax 和Jq Ajax
    JAVA调用Oracle存储过程
    Oracle存储过程包含三部分:过程声明,执行过程部分,存储过程异常。
    回到基础:封装集合
    如何摆脱工具类
    泛型的古怪与优雅
    Spring MVC + Hibernate + Maven: Crud操作示例
    JDBC性能小贴
  • 原文地址:https://www.cnblogs.com/PerkinsZhu/p/7466439.html
Copyright © 2011-2022 走看看