精华内容
下载资源
问答
  • java中Executors创建线程池三种方法

    万次阅读 2020-04-04 17:10:59
    个关键线程池的比较 1、创建单个线程(单例模式) public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, ...

    三个关键线程池的比较

    1、创建单个线程(单例模式)

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
    

    由于调用的ThreadPoolExecutor的构造方法的核心池大小和最大线程池均为1,所以该线程池只能存在一个线程。

    2、创建固定大小的线程池

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    

    我们可以看到,该创建线程池的方法提供了一个课传递的参数nThreads,该参数可以设置线程池的核心大小以及最大容量,即该线程池的固定大小。

    3、可以伸缩的线程池

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
    

    我们可以看到,这里的最大线程大小可以达到Integer的最大大小2147483647,一般情况下我们是用不了这么多线程的,想用这么多的线程,是需要强大的硬件设备的支持,我们可以看到在线程被创建后60s如果没有被调用就会被释放,关于这些参数我会在后面讲到。

    这几种方式创建的线程池都是通过创建ThreadPoolExecutor对象来实现的

    4、ThreadPoolExecutor

    我们来看一下这三个线程池创建时调用的ThreadPoolExecutor的构造方法

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
    

    我们看下这里面调用的this方法

    public ThreadPoolExecutor(int corePoolSize,	// 核心线程池大小
                              int maximumPoolSize,	// 最大线程池大小
                              long keepAliveTime,	// 超时了没有人调用就会释放
                              TimeUnit unit,	// 超时单位
                              BlockingQueue<Runnable> workQueue,	// 阻塞队列
                              ThreadFactory threadFactory,	// 线程工厂,创建线程线程的
                              RejectedExecutionHandler handler) {// 拒绝策略
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
            null :
        AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
    

    所以我们看到这些方法本质上都是调用了ThreadPoolExecutor的构造方法

    注意:虽然用Executors创建线程池可以方便我们的操作,但是阿里发布的 Java开发手册中强制线程池不允许使用 Executors 去创建,所以建议大家还是用ThreadPoolExecutor 来创建线程池

    ThreadPoolExecutor创建线程池参考https://blog.csdn.net/jjj___jjj/article/details/105314542

    展开全文
  • package ThreadPool; import java.util.concurrent.*;... * 创建线程池三种常用方法 */ public class ThreadPoplDemo { public static void main(String args[]) { CreateThreadPool1 (); } public...
    package ThreadPool;
    
    import java.util.concurrent.*;
    
    /**
     * 创建线程池的三种常用方法
     */
    public class ThreadPoplDemo {
        public static void main(String args[]) {
            CreateThreadPool1 ();
        }
    
    
        public static void CreateThreadPool1 (){
            //线程池里面的线程用完以后,还给线程池,不关闭;
            ExecutorService service = new ThreadPoolExecutor(
                    /**
                     * 核心线程数,当线程池初次创建时,是没有任何线程的;当有
                     * 请求发起时,线程池会创建核心线程, 在球球过程中,无论核
                     * 心线程是否闲置,线程池都会创建核心线程,知道满足数量为止
                     */
                    5,
                    /**
                     * 最大线程数,先有的核心线程,后面创建的为临时线程
                     */
                    10,
                    /**
                     * 存活时间。临时线程的存活时间,就是指临时线程闲置后的时间,时间一到就会销毁线程;
                     */
                    3000,
                    /**
                     * 时间单位,一般用毫秒
                     */
                    TimeUnit.MILLISECONDS,
                    /**
                     * 等待队列,用于存放还会处理的请求;
                     */
                    new ArrayBlockingQueue<Runnable>(10),
                    /**
                     * 拒绝服务器助手
                     */
                    new RejectedExecutionHandler() {
                        @Override
                        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                                System.out.print("请稍后尝试");
                        }
                    }
            );
            //通过线程池启动线程
            for (int i = 0;i<21;i++) {
                service.execute(new ClientRunble());
            }
            /**
             * 关闭线程池,当调用这个方法时,里面的线程不会立即销毁,只是不接受外部请求;
             * 只有内部的线程处理完后,才会销毁,使用线程池的好处是避免线程的频繁创建何销毁;
             * 从而节省cpu性能;
             */
            service.shutdown();
        }
    
    
        public  static void  CreateThreadPool2(){
            /**
             * 此种方法也可以创建线程池,但是此方法创建的线程池没有核心线程;
             * 只有临时线程;
             * 队列是同步队列;
             * 最大线程数无界;
             * 可以很好的响应客户端请求,大池子,小队列;
             * 因为不需要排队等待;
             * 这种线程池适用于短请求,如果都是长请求,可能导致线程一直创建二不销毁,最后造成内存溢出;
             *
             */
            ExecutorService service = Executors.newCachedThreadPool();
        }
    
        public void CreateThreadPool3(){
            /**
             *  小池子大队列:
             *  1.都是核心线程,没有临时线程;
             *  2.队列是无界队列,LinkedBlockingQueue<Runnable>()
             *  3.应用场景:这种线程池的作用:消峰限流。
             *  4.坏处:某些请求可能等待很长时间才处理,不能及时响应客户端;
             */
            ExecutorService service = Executors.newFixedThreadPool(10);
    
        }
    }
    
    
    class ClientRunble implements Runnable{
    
        @Override
        public void run() {
            System.out.println("处理客户请求");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    展开全文
  • 一、线程池 线程池的工作主要是控制运行的线程数量,把大于线程池线程数量的线程放到队列中,等到... 提高线程的可管理性,线程是稀缺资源,如果无限制的创建,不仅会消耗资源,还会降低系统的稳定性,使用线程池可...

    一、线程池

    线程池的工作主要是控制运行的线程数量,把大于线程池线程数量的线程放到队列中,等到线程池有空闲线程,再从队列取出任务来执行

    线程池优点:

    1. 降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁造成的消耗
    2. 提高响应速度,当任务到达时,任务可以不需要的等到线程创建就能立即执行
    3. 提高线程的可管理性,线程是稀缺资源,如果无限制的创建,不仅会消耗资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控

    二、创建线程池三种方式

    1.Excutors.newFixedThreadPool(int)

    创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待

    newFixedThreadPool创建的线程池corePoolSize和maximumPoolSize值是相等的,它使用的LinkedBlockingQueue

    2.Excutors.newSingleThreadExecutor()

    创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序执行

    newSingleThreadExecutor创建的线程池corePoolSize和maximumPoolSize值都设置为1,它使用的LinkedBlockingQueue

    3.Excutors.newCachedThreadPool()

    创建一个可缓存线程池,如果线程池长度超出处理需要,可灵活回收空闲线程,若无可回收,则新建线程

    newCachedThreadPool将corePoolSize设置为0,将maximumPoolSize设置为Integer.MAX_VALUE,使用的SynchronousQueue,多余的空闲线程的存活时间60秒

    三、线程池使用

    1.ThreadPoolExecutor

    线程池都是通过ThreadPoolExecutor实现的

    继承关系图:

    2.线程池使用

    public class PoolTest {
    
        public static void main(String[] args) {
            ExecutorService threadPool = Executors.newFixedThreadPool(3);
    //        ExecutorService service = Executors.newCachedThreadPool();
    //        ExecutorService service = Executors.newSingleThreadExecutor();
            try{
                for (int i = 0 ; i < 5; i++){
                    threadPool.submit(()->{
                        System.out.println(Thread.currentThread().getName());
                    });
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                threadPool.shutdown();
            }
        }
    
    }
    

    结果:

    四、线程池7大参数

    1.corePoolSize:线程池中的常驻核心线程数

    在创建了线程池后,当有请求任务来之后,就会安排池中的线程去执行请求任务;当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中

    2.maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1

    3.keepAliveTime:多余的空闲线程的存活时间

    当前线程池数量超过corePoolSize时,当空闲时间达到keepAliveTime值时,多余空闲线程会被销毁直到只剩下corePoolSize个线程为止,默认情况下,只有当线程池大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize

    4.unit:keepAliveTime的单位

    5.workQueue:任务队列,被提交单尚未被执行的任务

    6.threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程一般用默认的即可

    7.handler:拒绝策略

    表示当队列满了并且工作线程大于等于线程池的最大线程数(maximumPoolSize)时, 如何来拒绝请求执行的runnable的策略

    五、线程池底层工作原理

    1.在创建线程池后,等待提交过来的任务请求

    2.当调用execute()方法添加一个请求任务时,线程池会做以下判断

    如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务

    如果正在运行的线程数据大于或等于corePoolSize,那么这个任务放到队列

    如果这时候队列满了且正在运行的线程数量还小于maximumPoolsize,那么还是要创建非核心线程立刻执行这个任务

    如果队列满了且正在运行的线程数量大于或等于maximumPoolsize,那么线程池会启动饱和拒绝策略来执行

    3.当一个线程完成任务时,它会从队列中取下一个任务来执行

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

     

    六、JDK内置的拒绝策略

    拒绝策略,等待队列已经排满了,再也塞不下新任务了,同时,线程池中的max线程也到到了,无法继续为新任务服务,这时候我们就需要拒绝策略机制合理的处理这个问题

    内置拒绝策略均实现了RejectedExecutionHandler接口

    AbortPolicy(默认):直接抛出RejectedExecutionException异常阻止系统正常运行

    CallerRunsPolicy:“调用者运行”一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量

    DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务

    DiscardPolicy:直接丢弃任务,不予任务处理也不抛弃异常,如果允许任务丢失,这是最好的一种方案

    七、自定义线程池

    因为newFixedThreadPool、newSingleThreadExecutor使用的是new LinkedBlockingQueue<>()无限长度队列,newCachedThreadPool将maximumPoolSize设置为Integer.MAX_VALUE,在实际生产中可能会出现问题

    可以用ThreadPoolExecutor自定义线程池

    public class MyThreadPoolDemo {
        public static void main(String[] args) {
            ExecutorService threadPool = new ThreadPoolExecutor(
                    2,
                    5,
                    1L,
                    TimeUnit.SECONDS,
                    new LinkedBlockingQueue<>(3),
                    Executors.defaultThreadFactory(),
                    new ThreadPoolExecutor.DiscardOldestPolicy());
    
            try {
                for(int i = 0; i < 10; i++){
                    int temp = i;
                    threadPool.execute(()->{
                        System.out.println(Thread.currentThread().getName() + "\t 执行任务:" + temp);
                    });
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                threadPool.shutdown();
            }
        }
    
    }

    结果:

    因为要处理的线程10个,自定义线程设置corePoolSize=2,maximumPoolSize=5,workQueue大小为3,最多线程池有8个线程,再来线程便会启动拒绝策略,拒绝策略DiscardOldestPolicy,所有会抛弃队列中等待最久的任务

    成功执行了8个任务,丢失了2个任务

     

    更多请阅读

    Java创建线程池三种方式及自定义线程池

    展开全文
  • java 创建线程的三种方式、创建线程池的四方式

    万次阅读 多人点赞 2019-02-23 21:01:44
    概要: java创建线程的三种方式: ...java创建线程池的四方式: newCachedThreadPool 创建一个可缓存的线程池,如果线程池长度超过处理需求,可灵活回收空闲线程,若无可回收,则新建线程 newFixedThread...

    概要:

    java创建线程的三种方式:

    1.     继承Thread类创建线程类
    2.     实现Runnable接口
    3.     通过Callable和Future创建线程

       

    java创建线程池的四种方式:

         newCachedThreadPool 创建一个可缓存的线程池,如果线程池长度超过处理需求,可灵活回收空闲线程,若无可回收,则新建线程

        newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待

        newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行

        newSingleThreadExecutor 创建一个单线程化的线程池,它只会唯一的工作线程来执行任务,保证所有任务按照指定

    顺序(FIFO,LIFO,优先级)执行

     

    线程池的优点:

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

     

    第一 Java中创建线程主要有三种方式:

    1、继承Thread类创建线程类 (extends)

    (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体(线程体)

    (2)创建Thread子类的实例,即创建了线程对象。

    (3)调用线程对象的start()方法来启动该线程。  

      
    public class FirstThreadTest extends Thread{  
        int i = 0;  
        //重写run方法,run方法的方法体就是现场执行体  
        public void run()  
        {  
            for(;i<100;i++){  
            log.info(getName()+"  "+i);  
            }  
        }  
    
        public static void main(String[] args)  
        {  
            for(int i = 0;i< 100;i++)  
            {  
                log.info(Thread.currentThread().getName()+"  : "+i);  
                if(i==20)  
                {  
                    new FirstThreadTest().start();  
                    new FirstThreadTest().start();  
                }  
            }  
        }  
    } 

     

    上述代码中Thread.currentThread()方法返回当前正在执行的线程对象。GetName()方法返回调用该方法的线程的名字。

     

    2、通过Runnable接口创建线程类

    (1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。

    (2)创建 Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

    (3)调用线程对象的start()方法来启动该线程。

    public class RunnableThreadTest implements Runnable  
    {  
      
        private int i;  
        public void run()  
        {  
            for(i = 0;i <100;i++)  
            {  
               log.info(Thread.currentThread().getName()+" "+i);  
            }  
        }  
    
        public static void main(String[] args)  
        {  
            for(int i = 0;i < 100;i++)  
            {  
                log.info(Thread.currentThread().getName()+" "+i);  
                if(i==20)  
                {  
                    RunnableThreadTest runner= new RunnableThreadTest();  
                    new Thread(runner,"新线程1").start();  
                    new Thread(runner,"新线程2").start();  
                }  
            }  
        }   
    }  

     

    线程的执行流程很简单,当执行代码start()时,就会执行对象中重写的void run()方法,该方法执行完成后,线程就消亡了。

     

    3、通过Callable和Future创建线程

    (1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值

    public interface Callable
    {
      V call() throws Exception;
    }

    (2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方

    法的返回值。(FutureTask是一个包装器,它通过接受Callable来创建,它同时实现了Future和Runnable接口。)

    (3)使用FutureTask对象作为Thread对象的target创建并启动新线程。

    (4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值

    public class CallableThreadTest implements Callable<Integer>  
    {  
      
        public static void main(String[] args)  
        {  
            CallableThreadTest ctt = new CallableThreadTest();  
            FutureTask<Integer> ft = new FutureTask<>(ctt);  
            for(int i = 0;i < 100;i++)  
            {  
                log.info(Thread.currentThread().getName()+" 的循环变量i的值"+i);  
                if(i==20)  
                {  
                    new Thread(ft,"有返回值的线程").start();  
                }  
            }  
            try  
            {  
                log.info("子线程的返回值:"+ft.get());  
            } catch (InterruptedException e)  
            {  
                e.printStackTrace();  
            } catch (ExecutionException e)  
            {  
                e.printStackTrace();  
            }  
      
        }  
      
        @Override  
        public Integer call() throws Exception  
        {  
            int i = 0;  
            for(;i<100;i++)  
            {  
                log.info(Thread.currentThread().getName()+" "+i);  
            }  
            return i;  
        }  
      
    }  

     

    二、创建线程的三种方式的对比

    1、采用实现Runnable、Callable接口的方式创建多线程

          优势:

           线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。

           在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。

           劣势

         编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法

    2、使用继承Thread类的方式创建多线程

          优势:

          编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程

          劣势:

          线程类已经继承了Thread类,所以不能再继承其他父类。

    3、Runnable和Callable的区别

         (1) Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run()。

         (2) Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。

         (3) call方法可以抛出异常,run方法不可以。

         (4) 运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的

    完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果future.get()。

     

    第二 创建四种线程池的方式

    1、new Thread的弊端

    执行一个异步任务你还只是如下new Thread吗?

    new Thread(new Runnable() {
    
    
      @Override
    
      public void run() {
    
        // TODO Auto-generated method stub
    
        }
    
      }
    
    ).start();

     

    那你就out太多了,new Thread的弊端如下:

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

    相比new Thread,Java提供的四种线程池的好处在于:

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

    2、Java 线程池

    Java通过Executors提供四种线程池,分别为:

    newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
    newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
    newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
    newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。


    (1) newCachedThreadPool:

    创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。示例代码如下:

    ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    
      for (int i = 0; i < 10; i++) {
    
        final int index = i;
    
      try {
    
        Thread.sleep(index * 1000);
    
       } catch (InterruptedException e) {
    
          e.printStackTrace();
    
      }
    
    
    
       cachedThreadPool.execute(new Runnable() {
    
         @Override
    
         public void run() {
    
            log.info(index);
    
          }
    
       });
    
    }

    线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。

     

    (2) newFixedThreadPool:---  需要指定线程池的大小

    创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。示例代码如下:

    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
    
      for (int i = 0; i < 10; i++) {
    
      final int index = i;
    
    
      fixedThreadPool.execute(new Runnable() {
    
    
      @Override
    
      public void run() {
     
          try {
             log.info(index);
             Thread.sleep(2000);
          } catch (InterruptedException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
           }
        }
      });
    }

    因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。

    定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()。可参考PreloadDataCache。

     

    (3)newScheduledThreadPool:

    创建一个定长线程池,支持定时及周期性任务执行。延迟执行示例代码如下:

    ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
    
     scheduledThreadPool.schedule(new Runnable() {
    
    
          @Override
    
          public void run() {
    
             log.info("delay 3 seconds");
           }
    
     }, 3, TimeUnit.SECONDS);

    表示延迟3秒执行。

    定期执行示例代码如下:

    scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
    
          @Override
    
          public void run() {
    
              log.info("delay 1 seconds, and excute every 3 seconds");
    
          }
    
    }, 1, 3, TimeUnit.SECONDS);

    表示延迟1秒后每3秒执行一次。

    ScheduledExecutorService比Timer更安全,功能更强大

     

    (4)newSingleThreadExecutor:

    创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。示例代码如下:

    ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
    
    for (int i = 0; i < 10; i++) {
      final int index = i;
      singleThreadExecutor.execute(new Runnable() {
    
        @Override
        public void run() {
        try {
            log.info(index);
            Thread.sleep(2000);
         } catch (InterruptedException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
        }
      });
    }

    结果依次输出,相当于顺序执行各个任务。

    线程池的作用:

    线程池作用就是限制系统中执行线程的数量。

    根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率

    不高。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没

    有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;

    否则进入等待队列。

    为什么要用线程池:

    1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

    2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大

    约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

    Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的

    线程池接口是ExecutorService。

    比较重要的几个类:

    ExecutorService: 真正的线程池接口。

    ScheduledExecutorService: 能和Timer/TimerTask类似,解决那些需要任务重复执行的问题。

    ThreadPoolExecutor: ExecutorService的默认实现。

    ScheduledThreadPoolExecutor: 继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现。

    要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此

    在Executors类里面提供了一些静态工厂,生成一些常用的线程池。

    展开全文
  • 线程池介绍及创建线程池的4方式

    万次阅读 多人点赞 2019-06-10 16:40:27
    1. 什么是线程池 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序 都可以使用线程池。...第:提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源...
  • 创建线程池的四方式

    万次阅读 2019-02-22 09:41:40
    Executors创建的4种线程池的使用 Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 ...
  • java中创建线程池的四方式

    千次阅读 2019-02-22 17:41:23
    java中创建线程池的四方式 话不多说,直接上代码,可以先分析再运行,结合运行结果最有说服力 public class CreateThreadPool { public static void main(String[] args) { /*Java通过Executors提供四线程池...
  • 延时与定义执行的线程池,使用schedule执行1)创建线程池与执行2)代码示例3.ExecutorService接口的其他操作1)shutdown()与shutdownNow()2)submit的返回值二、线程池的实现原理、本文使用到的类1....
  • java创建线程池的4方式()

    千次阅读 2019-08-04 14:16:02
    创建一个定长线程池,支持定时及周期性任务执行。 延时执行 private static void scheduledThreadPool01(){ ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); ...
  • 线程池做的工作只要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,超出数量的线程排队等候,等其他线程执行完毕,再从队列中取出任务来执行。...
  • 线程池三方法: public static void main(String[] args) { Executors.newCachedThreadPool();// 请求多 就创建线程多 Executors.newFixedThreadPool(5);// 给定线程的线程池 Executors....
  • 文章目录Java创建线程的三种方式线程池的优点Java中创建线程池的两方式Executors工厂方法创建new ThreadPoolExecutor()自定义创建corePoolSize和maximumPoolSizeworkQueue任务队列拒绝策略 Java创建线程的三种方式...
  • java创建线程池

    2019-11-25 16:05:58
    线程池:是拿空间换时间的一手段;JDK1.5以后加入java.util.concurrent包 线程池有了很大的改观 例如:用户提交一个请求任务 服务器执行这个任务需要通过个阶段时间消耗,线程创建的时间,线程执行任务的时间...
  • C++创建线程池

    2018-11-17 12:32:33
    线程池是一多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在...
  • Executors创建线程池

    2020-05-22 10:34:51
    java jdk1.5提供线程池 在java.util.concurrent包下提供工厂类Executors用于生产线程池,Executors提供了4种线程池 newFixedThreadPool: 创建一个线程池,该线程池重用固定数量的从共享无界队列中运行的线程。 ...
  • 今天聊一聊为什么不推荐使用jdk自带的Executors静态方法创建线程池方法,最常见的就是以下这四: 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 核心...
  • 下面四个方法本质上都是调用ThreadPoolExecutor的构造方法: 1:Executors.newSingleThreadExecutor() 2:Executors.newFixedThreadPool(nThreads) 3:Executors.newCachedThreadPool() 4:Executors....
  • 用法讲解Executors创建线程池有多种方式,列举最重要的三种如下://创建一个包含指定数目线程的线程池,如果任务数量多于线程数量,那么没有执行的任务必须等待,直到有任务完成为止。 private static ...
  • 关于三种线程池三种队列区别:SynchronousQueue、LinkedBlockingQueue 和ArrayBlockingQueue,可以点击链接查看。https://blog.csdn.net/qq_26881739/article/details/80983495 最近线程池用的比较多,感觉挺...
  • 用ThreadPoolExecutor创建线程池的优点

    千次阅读 2018-09-14 16:28:30
    现在做开发的童鞋,越来越多的人在创建线程池用ThreadPoolExecutor,而不是用JDK提供的四种方法来创建 一、线程池的背景: 1、线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复...
  • 为什么要用线程池? 降低系统资源消耗。 提高线程可控性。 ...相比new Thread,Java提供的线程池的好处 ...重用存在的线程,减少对象创建、消亡的开销,...JDK8提供了五种创建线程池方法: 1.创建一个定长线程池,可...
  • 线程池创建: ExecutorService 方式一:首先引入:commons-lang3包 ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new BasicThreadFactory.Builder().namingPattern("example-...
  • 一、为什么要手动创建线程池? 我们之所以要手动创建线程池,是因为 JDK 自带的工具类所创建的线程池存在一定的弊端,那究竟存在怎么样的弊端呢?首先来回顾一下 JDK 中线程池框架的继承关系: JDK 线程池框架继承...
  • 看阿里巴巴编程手册时候会发现其中有一条:不允许使用Excutors来创建线程池,而是要使用ThreadPoolExecutor的方式来创建线程,那么为什么会有这个要求呢?我们通过代码来进行分析。 Excutors创建的线程池按照返回...
  • Executors工厂类创建线程池的底层实现

    千次阅读 多人点赞 2013-05-26 21:01:34
    上一篇介绍了ThreadPoolExecutor的基本使用,现在再来看看...三种创建线程池的工厂方法源码: // 无界线程池 public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_
  • 阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,通过源码分析禁用的原因。...根据返回的对象类型创建线程池可以分为类: 创建返回ThreadPoolExecutor
  • 看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,... Executors创建线程池的几方式 ThreadPoolExecutor对象 线程池执行任务逻辑和线程池参...
  • Executors创建线程池的几方式 ThreadPoolExecutor对象 线程池执行任务逻辑和线程池参数的关系 Executors创建返回ThreadPoolExecutor对象 OOM异常测试 如何定义线程池参数 线程池的定义 管理一组工作线程。通过...
  • 如果无法控制地创建线程,则可能会很快耗尽这些资源。 为了模拟并行性线程之间的上下文切换也由操作系统完成。一简单的观点是:产生的线程越多,每个线程花费在实际工作上的时间就越少。 线程池模式有助于节省多...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 138,477
精华内容 55,390
关键字:

创建线程池的三种方法