RejectedExecutionHandler 以及线程池的自行实现

RejectedExecutionHandler handler

拒绝方式/拒绝策略(线程池考察的重点)

我们知道,线程池有一个阻塞队列,当阻塞队列满了之后,继续添加任务,我们该如何去应对?

Java系统的四个处理方式

ThreadPoolExecutor.AbortPolicy

直接抛出异常,这样做的话,整个线程池就不干活了

ThreadPoolExecutor.CallerRunsPolicy

谁是添加这个新任务的线程,就谁去执行这个任务(注意与第四个任务进行区分)

ThreadPoolExecutor.DiscardOldestPolicy

丢弃最早的任务,执行新的任务

ThreadPoolExcutor.DiscardPolicy

丢弃新的任务(就没有线程去执行这个任务了)

线程池的自行实现

class MyThreadPool{
    //创建一个阻塞队列
    BlockingQueue<Runnable> queue=new LinkedBlockingQueue<>();
    //首先,线程池么,可肯定要有一个添任务的方法
    public void submit(Runnable runnable) throws InterruptedException {
    //其次,我们需要将新的任务添加到一个阻塞队列中去
    queue.put(runnable);
    }
    //然后我们需要有方法去创建线程(固定数量的)
    public MyThreadPool(int n){//n是指定有多少个线程
        for (int i = 0; i < n; i++) {
            Thread t=new Thread(()->{
               while(true){
                   try {
                       //取出要执行的任务
                       Runnable runnable=queue.take();
                       runnable.run();//执行该任务
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
            });
            t.start();
        }
    }
}
//自行实现线程池
public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPool myThreadPool=new MyThreadPool(4);
        for (int i = 0; i < 100; i++) {
            myThreadPool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"hello");
                    //Thread.currentThread()获取线程实例
                }
            });
        }

    }
}

运行结果如下由于此时线程的调度是随机的,当前给这个线程池中插入的任务,在执行的时候,也不一定是N个线程的工作完全均等,但是从统计意义上说,任务是均等的,另外,当前线程做的任务就只是一个简单的打印,花的时间短,很有可能你刚给A线程分配好任务,但是A线程一下就执行完了,那么下一次就很有可能还是A线程分配并执行同样的任务.

那么问题来了,创建线程池的时候,线程的个数是咋来的?

线程池的线程数目,网络上有很多说法,比如,假设CPU逻辑核心数为N,线程池线程个数:N,N+1,1.2*N,1.5*N,2*N....(但是这些都不准确!!!)不同的项目中,线程要做的工作,是不一样的

有的线程的工作是"CPU密集型",线程的工作全是运算在这种情况下,CPU大部分工作都是要在CPU上完成的.CPU得给他安排核心去完成工作才可以有进展,如果CPU是N个核心,当你线程数量也是N的时候,理想情况,每个核心上一个线程,如果搞很多的线程,线程也就是在排队等待,不会有新的进展.有的线程的工作是"IO密集型",读写文件,等待用户输入,网络通信等

这类型的操作涉及到大量的等待时间,在等待的过程中,没有使用CPU,这样的线程就算更多一些也不会给CPU造成太大的负担,比如CPU是16个核心,写32个线程,由于是IO密集型的,这里的大部分线程都在等,都不消耗CPU,反而CPU的占用情况还很低

实际开发过程中,一个线程往往是一部分工作是CPU密集的,一部分工作是IO密集的,此时,一个线程,几成是在CPU上运行,几成是在等待IO,这个是说不好的,这里更好的做法,即使通过实验的方式,来找到合适的线程数,也就是对其进行性能测试,尝试不同的线程数目,尝试过程中,找到性能和系统资源开销比较均衡的数值.

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java中的线程池是一种用于管理和复用线程的机制,它可以提高线程的利用率和性能。Java提供了一个内置的线程池实现——ThreadPoolExecutor,同时也提供了Executors工厂类来创建不同类型的线程池。 要自定义线程池的配置,可以通过创建ThreadPoolExecutor对象并设置相应的参数来实现。以下是一些常用的线程池配置选项: 1. 核心线程数(corePoolSize):线程池中保持活动状态的最小线程数。如果线程池中的线程数小于核心线程数,即使有空闲线程,也会创建新的线程来处理任务。 2. 最大线程数(maximumPoolSize):线程池中允许存在的最大线程数。当任务数量超过核心线程数且工作队列已满时,线程池会创建新的线程来处理任务,直到达到最大线程数。 3. 空闲线程存活时间(keepAliveTime):当线程池中的线程数大于核心线程数时,空闲线程的存活时间。超过这个时间,空闲线程会被终止,直到线程池中的线程数不超过核心线程数。 4. 工作队列(workQueue):用于存储等待执行的任务的队列。Java提供了多种类型的工作队列,如ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等。 5. 拒绝策略(rejectedExecutionHandler):当线程池无法接受新的任务时,采取的处理策略。常见的策略有AbortPolicy(默认策略,抛出RejectedExecutionException异常)、CallerRunsPolicy(由调用线程执行任务)、DiscardPolicy(丢弃任务)和DiscardOldestPolicy(丢弃队列中最旧的任务)。 下面是一个示例代码,展示如何自定义线程池配置并使用线程池: ```java import java.util.concurrent.*; public class ThreadPoolExample { public static void main(String[] args) { // 创建线程池 ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, // 核心线程数 5, // 最大线程数 1, // 空闲线程存活时间 TimeUnit.MINUTES, // 时间单位 new ArrayBlockingQueue<>(10), // 工作队列 new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 ); // 提交任务给线程池 for (int i = 0; i < 10; i++) { final int taskId = i; executor.execute(() -> { System.out.println("Task " + taskId + " is running."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Task " + taskId + " is completed."); }); } // 关闭线程池 executor.shutdown(); } } ``` 在上面的示例中,我们创建了一个核心线程数为2,最大线程数为5,工作队列容量为10的线程池。然后,我们提交了10个任务给线程池执行。每个任务会打印一条消息,并休眠1秒钟模拟任务的执行。最后,我们调用了线程池的shutdown()方法来关闭线程池

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值