javaSE高级开发多线程——7 线程池

在java中的线程池实际上是并发框架,它主要用于异步或者并发执行任务的程序。它的优点主要有三个:
(1)降低资源消耗:通过重复利用已经创建的线程降低线程创建和销毁带来的消耗。
(2)提高响应速度:当任务达到时,任务可以不需要等待线程创建就能立即执行。
(3)提高线程的可管理性:使用线程池可以统一进行线程分配、调度和监控。
1.线程池的实现原理

2.线程池的使用
(1)线程池的创建:手动自定义的创建线程池

package com.wschase.threadchi;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;


/**手动创建一个线程池
 * Author:WSChase
 * Created:2019/1/13
 */
public class TestThreadPool {
    public static void main(String[] args) {
        ThreadPoolExecutor executor=new
                ThreadPoolExecutor(5,10,
                1,
                TimeUnit.SECONDS,//时间单位
                new ArrayBlockingQueue<>(15),
                new ThreadPoolExecutor.DiscardPolicy()//丢弃掉
                );


        ThreadPoolExecutor executor2=new
                ThreadPoolExecutor(5, 10,
                1,
                TimeUnit.SECONDS,//时间单位
                new ArrayBlockingQueue<>(15),
                new ThreadFactory() {
                    private final AtomicInteger threadId=new AtomicInteger(1);
                    //把创建线程的逻辑交给用户:
                    //(1)用户可以决定这个线程在这是守护线程还是用户线程
                    //(2)用户可以在这把线程创建好以后给线程起名字

                    @Override
                    public Thread newThread(Runnable r) {
                        Thread thread=new Thread(r);
                        thread.setName("自定义线程"+String.valueOf(threadId.getAndAdd(1)));
                    return thread;
                    }
                }
        );
        for(int i=0;i<10;i++){

        executor2.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        });

    }
        }
}

(2)向线程池提交任务

package com.wschase.threadchi;

import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;


/**手动创建一个线程池
 * Author:WSChase
 * Created:2019/1/13
 */
public class TestThreadPool {
    public static void main(String[] args) {
        //1)创建线程池,只能指定那些参数的大小
        ThreadPoolExecutor executor1=new
                ThreadPoolExecutor(5,10,
                1,
                TimeUnit.SECONDS,//时间单位
                new ArrayBlockingQueue<>(15),
                new ThreadPoolExecutor.DiscardPolicy()//丢弃掉
                );


        //2)创建线程池--可以自己定义名字
        ThreadPoolExecutor executor2=new
                ThreadPoolExecutor(5, 10,
                1,
                TimeUnit.SECONDS,//时间单位
                new ArrayBlockingQueue<>(15),
                new ThreadFactory() {
                    private final AtomicInteger threadId=new AtomicInteger(1);
                    //把创建线程的逻辑交给用户:
                    //(1)用户可以决定这个线程在这是守护线程还是用户线程
                    //(2)用户可以在这把线程创建好以后给线程起名字

                    @Override
                    public Thread newThread(Runnable r) {
                        Thread thread=new Thread(r);
                        thread.setName("自定义线程"+String.valueOf(threadId.getAndAdd(1)));
                    return thread;
                    }
                }
        );
        for(int i=0;i<10;i++){

            //2.提交
            //1)提交的是Runnable
            executor2.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                }
         });

            //2)提交的是Callable
            Future<Integer> future=executor2.submit(new Callable<Integer>() {

                @Override
                public Integer call() throws Exception {
                    return new Random().nextInt(100);
                }
            });

            try {
                System.out.println(future.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
}

(3)关闭线程池
1)shutdown:平滑关闭线程池
2)shutdownNow:非平滑关闭线程池——有可能导致正在执行的任务不能完成

package com.wschase.threadchi;

import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;


/**手动创建一个线程池
 * Author:WSChase
 * Created:2019/1/13
 */
public class TestThreadPool {
    public static void main(String[] args) {
        //1)创建线程池,只能指定那些参数的大小
        ThreadPoolExecutor executor1=new
                ThreadPoolExecutor(5,10,
                1,
                TimeUnit.SECONDS,//时间单位
                new ArrayBlockingQueue<>(15),
                new ThreadPoolExecutor.DiscardPolicy()//丢弃掉
                );


        //2)创建线程池--可以自己定义名字
        ThreadPoolExecutor executor2=new
                ThreadPoolExecutor(5, 10,
                1,
                TimeUnit.SECONDS,//时间单位
                new ArrayBlockingQueue<>(15),
                new ThreadFactory() {
                    private final AtomicInteger threadId=new AtomicInteger(1);
                    //把创建线程的逻辑交给用户:
                    //(1)用户可以决定这个线程在这是守护线程还是用户线程
                    //(2)用户可以在这把线程创建好以后给线程起名字

                    @Override
                    public Thread newThread(Runnable r) {
                        Thread thread=new Thread(r);
                        thread.setName("自定义线程"+String.valueOf(threadId.getAndAdd(1)));
                    return thread;
                    }
                }
        );
        for(int i=0;i<10;i++){


            //1.创建
//        executor2.execute(new Runnable() {
//            @Override
//            public void run() {
//                System.out.println(Thread.currentThread().getName());
//            }
//        });


            //2.提交
            //1)提交的是Runnable
            executor2.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                }
         });
            //(3)关闭线程池
            //具体用哪一个由我们的任务来决定
        //1)shutdown安全关闭-->平滑关闭线程池
        executor2.shutdown();
        System.out.println(executor2.isShutdown());
        System.out.println(executor2.isTerminated());
        //2)shutdownNow():非平滑关闭,有可能正在执行的任务不能完成
    }
}

3.合理配置线程池——就是知道我们的线程池中应该创建多少个线程等
(1)任务类型:那么我们必须要掌握两种任务类型,不同类型的任务它的线程池的指标是不同的。
1)CPU密集型:你的任务是在CPU里面进行一些加减运算,这就叫CPU密集型。此外,它在整个运算过程中不需要我们的磁盘、网络、数据库、文件。
2)I/O密集型:与我们计算机的输入输出有关系。运算速度慢,很可能会等待,等待与我们的CPU没有关系,只与我们的网络有关。
3)混合型:既有CPU又有I/O。
(2)任务优先级:高、中、低
(3)任务时间:长、中、短
如何分配线程到线程池:
CPU密集型:配置nCPU+1个线程的线程池
I/O密集型:配置2*nCPU个线程的线程池
获取当前CPU核数:Runtime.getRuntime.availableProcessors()
4.ThreadPoolExcutor详解
对于Executor框架最核心的类就是ThreadPoolExcutor了,它是线程池的实现类。通过Executor框架的工具类Executors可以创建3种类型的ThreadPoolExcutor。
(1)创建无大小限制的线程池:public static ExecutorService newCachedThreadPool()
特点:可以随便加任务,只要不超过int的最大值就好。
(2)创建固定大小的线程池:public static ExecutorService newFixedThreadPool(int nThreads)
(3)单线程池:public static ExecutorService new SingleThreadExecutor()

package com.wschase.threadchi;

import java.time.LocalDateTime;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**对Executors进行详解
 * Author:WSChase
 * Created:2019/1/13
 */
public class TestExecutors {

    /**
     * 适用于:服务器负载比较高对资源有限制,可以采用固定线程数
     */
    public static void code1(){
        //1.固定数量的线程池——适用于
        ExecutorService executorService= Executors.newFixedThreadPool(5);
        final AtomicInteger count=new AtomicInteger(0);
        for(int i=0;i<100;i++){
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    //提交任务
                    System.out.println(Thread.currentThread().getName()+"=0"+count.getAndAdd(1));
                }
            });
        }
        executorService.shutdown();

    }

    /**
     * 适用于:任务按照顺序执行
     */
    public static void code2(){
        //2.SingleThreadPoolExecutor单线程的线程池
        ExecutorService executorService= Executors.newSingleThreadExecutor();
        final AtomicInteger count=new AtomicInteger(0);
        for(int i=0;i<100;i++){
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    //提交任务
                    System.out.println(Thread.currentThread().getName()+"="+count.getAndAdd(1));
                }
            });
        }
        executorService.shutdown();

    }

    /**
     * 适用于:任务多但执行时间短或者服务器负载比较小
     */
    public static void code3(){
        //3.缓存线程
        ExecutorService executorService= Executors.newCachedThreadPool();
        final AtomicInteger count=new AtomicInteger(0);
        for(int i=0;i<10000;i++){
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    //提交任务
                    System.out.println(Thread.currentThread().getName()+"="+count.getAndAdd(1));
                }
            });
        }
        executorService.shutdown();

    }
    public static void main(String[] args) {

        //4.任务调度——适用于定时的处理一些任务
       ScheduledExecutorService scheduledExecutorService= Executors.newScheduledThreadPool(5, new ThreadFactory() {
            private final AtomicInteger threadId=new AtomicInteger(1);
            @Override
            public Thread newThread(Runnable r) {
                Thread thread=new Thread(r);
                thread.setName("调度任务线程"+threadId.getAndAdd(1));
                return thread;
            }
        });


           //1)一次性任务
           scheduledExecutorService.schedule(
                   new Runnable() {
               @Override
               public void run() {
                   System.out.println("这是一个一次任务");
               }
           },1,TimeUnit.SECONDS);

           //2)周期性任务
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("这是一个周期性任务"+LocalDateTime.now().toString()+""+Thread.currentThread().getName());
            }
        },1,2,TimeUnit.SECONDS);
        //当我们调用shutdown后将会直接全部终止,不能执行;所以我们的定时任务一般不会调用shutdown
        scheduledExecutorService.shutdown();

    }
}

猜你喜欢

转载自blog.csdn.net/ZhuiZhuDream5/article/details/86432600
今日推荐