Bootstrap

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,这个是说不好的,这里更好的做法,即使通过实验的方式,来找到合适的线程数,也就是对其进行性能测试,尝试不同的线程数目,尝试过程中,找到性能和系统资源开销比较均衡的数值.

;