JAVA实现多线程的四种方式和 ThreadPoolExecutor线程池内容详解 七大参数 拒绝策略 自定义线程池

JAVA多线程的四种方式 线程池详细解析

JAVA多线程四种方式

java中实现线程的4种方式:

  • 1.继承Thread类 重写run方法
  • 2.实现Runnable接口 实现run方法
  • 3.继承Callable接口 实现call方法 使用futureTask调用 (有返回值/可处理异常)

[以上三种在平常业务代码种均不使用.]

[应该将所有的多线程异步任务都交给线程池执行]

  • 4.线程池(线程复用;控制最大并发数;管理线程)

    • 降低资源的消耗

      • 通过重复利用已经创建好的线程降低线程的创建和销毁带来的损耗
    • 提高响应速度

      • 因为线程池中的线程数没有超过最大上限时,有的线程处于等待分配任务的状态,当任务来时无需创建新的线程就能执行
    • 提高线程的可管理性

      • 线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来的系统开销.无线的创建和销毁线程不仅小号系统资源,还降低系统的稳定性,使用线程池进行统一分配

1.继承Thread类 重写run方法

public class ThreadTest {
     
    public  static void main(String args[]){
     
        System.out.println("main start ....");
//        1.继承Thread类 重写run方法
        new Thread01().start();
        System.out.println("main end ....");
    }
    public static class Thread01 extends  Thread{
     
        @Override
        public void run() {
     
            System.out.println("1.继承Thread类 重写run方法");
        }
    }
}

2.实现Runnable接口 实现run方法

public class ThreadTest {
     
    public  static void main(String args[]){
     
        System.out.println("main start ....");
//         2.实现Runnable接口 实现run方法
        new Thread(new Runnable01()).start();
        System.out.println("main end ....");
    }
    public static class Runnable01 implements  Runnable{
     
        @Override
        public void run() {
     
            System.out.println("2.实现Runnable接口 实现run方法");
        }
    }
}

3.继承Callable接口 实现call方法 使用futureTask调用 (有返回值/可处理异常)

public class ThreadTest {
     
    public  static void main(String args[]) throws ExecutionException, InterruptedException {
     
        System.out.println("main start ....");
//        3.继承Callable接口 实现call方法 使用futureTask调用  (有返回值/可处理异常)
        Callable01 callable01 = new Callable01();
        FutureTask<Integer> futureTask = new FutureTask<>(callable01);
        new Thread(futureTask).start();
        //使用futureTask 获取返回值  会阻塞等待
        System.out.println(futureTask.get());
        System.out.println("main end ....");
    }
    public static class Callable01 implements Callable<Integer>{
     

        @Override
        public Integer call() throws Exception {
     
            System.out.println("3.继承Callable接口 实现call方法 使用futureTask调用  (有返回值/可处理异常)");
            return new Integer(200);
        }
    }
}

4.线程池

4.1基础线程池的应用

public class ThreadTest {
     
    //正常情况保证一个项目中只有少数线程池,每个异步任务,线程池让他自己取执行
    //Executors.newFixedThreadPool(10); 使用工具类生成容量为10的线程池
    //自定义线程池使用  new ThreadPoolExecutor();  自定义七大参数
    public static ExecutorService service = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
     
        System.out.println("main start ....");
        try{
     
            service.execute(()->{
     
                System.out.println("4.线程池");
            });
        }catch (Exception e){
     
                e.printStackTrace();
        }finally{
     
            service.shutdown();
        }
        System.out.println("main end ....");
    }

}

4.2 Executors 辅助工具类

Executors.newFixedThreadPool(int);  //创建固定容量的线程池
Executors.newSingleThreadExecutor();  //创建一个只有1个工作线程的线程池
Executors.newCachedThreadPool() //创建一个可扩容的线程池。执行很多短期异步任务,线程池根据需要创建新线程,但在先前构造的线程可用时将重用他们。可扩容。
public class MyThreadPoolDemo {
     
    public  static void main(String args[]){
     
        //固定容量的线程池
//        ExecutorService threadPool =Executors.newFixedThreadPool(5); //创建一个有5个工作线程的线程池
//        ExecutorService threadPool =Executors.newSingleThreadExecutor(); //创建一个只有1个工作线程的线程池
        ExecutorService threadPool =Executors.newCachedThreadPool();  //创建一个可扩容的线程池
        try{
     
            for (int i = 1; i <10; i++) {
     
                //从线程池中使用一个工作线程
                threadPool.execute(()->{
     
                    System.out.println(Thread.currentThread().getName());
                });
            }
        }catch (Exception e){
     

        }finally{
     
            //任务结束 归还线程
            threadPool.shutdown();
        }
    }
}

以上三个Executors API底层均使用ThreadPoolExecutor使用不同的参数实现
JAVA实现多线程的四种方式和 ThreadPoolExecutor线程池内容详解 七大参数 拒绝策略 自定义线程池_第1张图片

4.3 ThreadPoolExecutor 的七大参数分析

JAVA实现多线程的四种方式和 ThreadPoolExecutor线程池内容详解 七大参数 拒绝策略 自定义线程池_第2张图片

  • 1、corePoolSize:线程中的常驻核心线程数

  • 2、maxmunPoolSize:线程池中能够容纳同时执行的最大线程数,此值必须大于1

  • 3、keepAliveTime:多余空闲线程的存活时间。当前池中线程数量超过corePoolSize时&&当空闲时间达到keepAliveTime时,多余线程会被销毁直到剩下corePoolSize个线程为止(过剩策略)

  • 4、unit:keepAliveTime的单位

  • 5、workQueue:任务阻塞队列,被提交但尚未被执行的任务(不够策略)

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

  • 7、handler:拒绝策略,表示当任务阻塞队列满了,并且共工作线程大于等于线程池的最大线程数(maxmunPoolSize)时,如何拒绝请求执行的Runnable策略(饱满策略)

4.4 ThreadPoolExecutor工作原理

  • 1、在创建了线程池后,开始等待请求。

  • 2、当调用execute()方法添加一个请求任务时,线程池会做出如下判断:

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

    ​ 2.2如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务放入队列;

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

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

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

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

4.5 自定义线程池

使用7大参数自定义线程池(最主要的参数是拒绝策略)

public class MyThreadPoolDemo {
     
    public  static void main(String args[]){
     
       ExecutorService threadPool = new ThreadPoolExecutor(2,
                5,
                2L,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    }
}

四大拒绝策略:

1、ThreadPoolExecutor.AbortPolicy(); 直接抛出RejectExecutionException 异常阻止系统正常运行

2、ThreadPoolExecutor.CallerRunsPolicy(); 调用者运行 一中调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量

3、ThreadPoolExecutor.DiscardOldestPolicy(); 抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务

4、ThreadPoolExecutor.DiscardPolicy(); 该策略默默的丢弃无法处理的任务,不予任何处理也不抛出异常。如果允许任务丢失,这是一个最好的策略。

机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量

3、ThreadPoolExecutor.DiscardOldestPolicy(); 抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务

4、ThreadPoolExecutor.DiscardPolicy(); 该策略默默的丢弃无法处理的任务,不予任何处理也不抛出异常。如果允许任务丢失,这是一个最好的策略。

你可能感兴趣的:(JAVA,8,知识学习,java,并发编程,面试,多线程)