Java多线程4种拒绝策略

一、简介

在Java多线程编程中,我们通常使用线程池来管理和调度任务。线程池由一组预先创建的线程组成,可以重复利用这些线程来执行多个任务,避免频繁地创建和销毁线程而带来的性能开销。

当线程池中的任务队列已满且无法再接受新的任务时,就需要采取拒绝策略来处理这种情况。拒绝策略定义了当无法再接受新的任务时如何处理这些被拒绝的任务。

Java提供了四种常见的拒绝策略:

  1. AbortPolicy(抛出异常):默认的拒绝策略。当任务无法被提交给线程池时,会直接抛出RejectedExecutionException异常。

  2. CallerRunsPolicy(调用者运行):当任务无法被提交给线程池时,会由提交任务的线程自己执行该任务。

  3. DiscardPolicy(直接丢弃):当任务无法被提交给线程池时,直接丢弃该任务,没有任何提示或处理。

  4. DiscardOldestPolicy(丢弃最旧任务):当任务无法被提交给线程池时,会丢弃队列中最早的一个任务,然后尝试再次提交当前任务。

二、AbortPolicy拒绝策略

A. 概述

AbortPolicy是ThreadPoolExecutor的默认拒绝策略,当任务无法被提交给线程池时,会直接抛出RejectedExecutionException异常。

B. 拒绝策略实现原理

实现RejectedExecutionHandler接口,在rejectedExecution方法中抛出异常。

public class AbortPolicy implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString());
    }
}

C. 应用场景

适用于对任务提交失败要求敏感的场景,需要明确知道任务是否被接受并执行。

D. 使用示例

当线程池的任务队列和线程队列都已满的情况下执行决绝策略

public class Task implements Runnable {

    private final int index;

    public Task(int index) {
        this.index = index;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":" + index);
    }
}


public class Main {

    public static void main(String[] args) {
        // 创建线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1, 0L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1),
                new ThreadPoolExecutor.AbortPolicy());
        try {
            // 提交任务
            threadPool.execute(new Task(1));
            threadPool.execute(new Task(2));
            threadPool.execute(new Task(3));
        } catch (RejectedExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭线程池
            threadPool.shutdown();
        }
    }
}

三、CallerRunsPolicy拒绝策略

A. 概述

CallerRunsPolicy是一种简单的拒绝策略,当任务无法被提交给线程池时,会由提交任务的线程自己执行该任务。

B. 拒绝策略实现原理

实现RejectedExecutionHandler接口,在rejectedExecution方法中使用提交任务的线程来执行任务。

public class CallerRunsPolicy implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run();
        }
    }
}

C. 应用场景

适用于对任务提交失败要求较低的场景,通过调用线程来执行任务,避免任务丢失。

D. 使用示例

public class Task implements Runnable {

    private final int index;

    public Task(int index) {
        this.index = index;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":" + index);
    }
}
public class Main {

    public static void main(String[] args) {
        // 创建线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1, 0L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1),
                new ThreadPoolExecutor.CallerRunsPolicy());
        try {
            // 提交任务
            threadPool.execute(new Task(1));
            threadPool.execute(new Task(2));
            threadPool.execute(new Task(3));
        } catch (RejectedExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭线程池
            threadPool.shutdown();
        }
    }
}

在这里插入图片描述

四、DiscardPolicy拒绝策略

A. 概述

DiscardPolicy是一种简单的拒绝策略,当任务无法被提交给线程池时,会直接丢弃该任务,没有任何提示或处理。

B. 拒绝策略实现原理

实现RejectedExecutionHandler接口,在rejectedExecution方法中不做任何操作,即丢弃任务。

public class DiscardPolicy implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        // Do nothing, discard the task
    }
}

C. 应用场景

适用于对任务提交失败不敏感的场景,对任务丢失没有特殊要求。

D. 使用示例

public class Task implements Runnable {

    private final int index;

    public Task(int index) {
        this.index = index;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":" + index);
    }
}
public class Main {

    public static void main(String[] args) {
        // 创建线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1, 0L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1),
                new ThreadPoolExecutor.DiscardOldestPolicy());
        try {
            // 提交任务
            threadPool.execute(new Task(1));
            threadPool.execute(new Task(2));
            threadPool.execute(new Task(3));
        } catch (RejectedExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭线程池
            threadPool.shutdown();
        }
    }
}

在这里插入图片描述

五、DiscardOldestPolicy拒绝策略

A. 概述

DiscardOldestPolicy是一种拒绝策略,当任务无法被提交给线程池时,会丢弃最早的一个任务,然后尝试再次提交。

B. 拒绝策略实现原理

实现RejectedExecutionHandler接口,在rejectedExecution方法中从队列中获取最早的任务并丢弃,再次提交当前任务。

public class DiscardOldestPolicy implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            e.getQueue().poll();
            e.execute(r);
        }
    }
}

C. 应用场景

适用于对新任务优先级比较高的场景,可以丢弃旧的任务以保证及时处理新任务。

D. 使用示例

public class Task implements Runnable {

    private final int index;

    public Task(int index) {
        this.index = index;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":" + index);
    }
}
public class Main {

    public static void main(String[] args) {
        // 创建线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1, 0L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(2),
                new ThreadPoolExecutor.DiscardOldestPolicy());
        try {
            // 提交任务
            threadPool.execute(new Task(1));
            threadPool.execute(new Task(2));
            threadPool.execute(new Task(3));
            threadPool.execute(new Task(4));
        } catch (RejectedExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭线程池
            threadPool.shutdown();
        }
    }
}

在这里插入图片描述

六、总结

各种拒绝策略的特点和适用场景

  • AbortPolicy:对任务提交失败要求敏感,需要明确知道任务是否被接受并执行。
  • CallerRunsPolicy:对任务提交失败要求较低,通过调用线程来执行任务,避免任务丢失。
  • DiscardPolicy:对任务提交失败不敏感,对任务丢失没有特殊要求。
  • DiscardOldestPolicy:适用于新任务优先级高,丢弃旧任务以保证及时处理新任务。
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java多线程参数设置包括线程池的七大参数,其中包括corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory和handler。下面是这些参数的详细介绍: 1. corePoolSize:核心线程数,即线程池中一直保持的线程数,即使它们处于空闲状态。如果提交的任务数大于corePoolSize,线程池就会创建新的线程来处理任务,直到线程数达到maximumPoolSize。 2. maximumPoolSize:线程池中允许的最大线程数。如果提交的任务数大于maximumPoolSize,线程池就会拒绝处理任务并抛出异常。 3. keepAliveTime:线程池中空闲线程的存活时间。如果线程池中的线程数大于corePoolSize,那么当线程空闲时间达到keepAliveTime时,多余的线程就会被销毁直到只剩下corePoolSize个线程为止。 4. unit:keepAliveTime的时间单位,可以是秒、毫秒、微秒等。 5. workQueue:任务队列,用于保存等待执行的任务。常用的有ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等。 6. threadFactory:线程工厂,用于创建新的线程。可以自定义线程工厂来设置线程的名称、优先级等属性。 7. handler:拒绝策略,用于处理无法处理的任务。常用的有AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy、DiscardPolicy等。 下面是一个示例代码,演示如何设置线程池的参数: ```java ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, // corePoolSize 4, // maximumPoolSize 60, // keepAliveTime TimeUnit.SECONDS, // unit new ArrayBlockingQueue<Runnable>(10), // workQueue Executors.defaultThreadFactory(), // threadFactory new ThreadPoolExecutor.AbortPolicy() // handler ); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮卡冲撞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值