Java线程池小结

目录

一.什么是线程池

二.线程池的好处是什么

 三.四种基本线程池及其使用

newCachedThreadPool

 newFixedThreadPool

newScheduledThreadPool 

newSingleThreadExecutor

线程池的四种拒绝策略

选择一:AbortPolicy

选择二:CallerRunsPolicy

选择三:DiscardPolicy

选择四:DiscardOldestPolicy


一.什么是线程池

简单来说,就是在系统的内存里面开辟一个容器用来存放线程

一旦线程结束之后,系统不会立刻回收销毁该线程,而是等他继续在容器里面

如果有其他任务需要调用该线程,就直接从容器里面拿出来

从而不必重新new和销毁线程

二.线程池的好处是什么

降低资源销毁:通过重复利用已经创建的线程,降低线程创建和销毁造成的消耗。
提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行。
防止服务器过载:形成内存溢出,或者CPU耗尽。.
提高线程的可管理性:线程是稀缺资源,如果无限制地创建,不仅会消耗资源,还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控。

 三.四种基本线程池及其使用

newCachedThreadPool

创建一个无最大容量的线程池

如果当前池子里的线程超过正在处理的线程数量,可回收空闲线程,如果池内没有该线程,则向池中放入一个新线程

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class mode9 {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            int j = i;
            pool.execute(()->{
                System.out.println(Thread.currentThread().getName() + "," + j);
            });

        }
    }
}

Java线程池小结_第1张图片

 

 newFixedThreadPool

创建一个有容量的线程池

可控制线程最大并发数,超出的线程会在队列中等待

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class demo10 {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 3; i++) {
            int j = i;
            pool.execute(()->{
                System.out.println(Thread.currentThread().getName()+j);
            });
        }
    }
}

Java线程池小结_第2张图片

newScheduledThreadPool 

创建一个有容量,并且能控制运行时间的线程池

public class demo11 {
    public static void main(String[] args) {
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
        for (int i = 0; i < 5; i++) {
            int j = i;
            pool.schedule(()->{
                System.out.println(Thread.currentThread().getName()+j);
            },3,TimeUnit.SECONDS);
        }
    }
}

Java线程池小结_第3张图片

newSingleThreadExecutor

采取优先级方式,从始至终都只有一个线程在运行(效率降低,安全性提升)

和第一个newCachedThreadPool基本上没什么区别,就是在他的基础上限定了只能同时运行一个罢了

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class demo12 {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 5; i++) {
            int j = i;
            pool.execute(()->{
                System.out.println(Thread.currentThread().getName()+j);
            });
        }
    }
}

线程池的四种拒绝策略

1.AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满,默认该方式。
2.CallerRunsPolicy:直接调用execute来执行当前任务。
3.DiscardPolicy:丢弃任务,但是不抛出异常。
4.DiscardOldestPolicy:抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。先从任务队列中弹出最先加入的任务,空出一个位置,然后再次执行execute方法把任务加入队列。

 对于上面四种方式我们来举例

假如说,你正在打游戏,这个时候你的老板突然打电话来让你去工作,你就有如下四种选择

选择一:AbortPolicy

哇的一声,哭出来,表示日子过不下去了,打游戏都不让我打了

这个时候,因为你在哭,不仅游戏没有继续打,而且老板让你去工作这件事也没执行

两件事都同时停下了(报错)

选择二:CallerRunsPolicy

直接回怼老板:自己开的公司,就该自己去做事情,别麻烦我

老板听到这句话,只好创建一个属于老板自己的线程,自己去开始工作

(注意,这里老板创建了一个属于自己的进程)

(也就是说发起者创建了一个属于自己的进程来执行,而不要你执行了)

选择三:DiscardPolicy

你无视了老板的电话,继续打游戏

这样老板也不知道你什么情况

你任然能继续你手头的工作而且不会报错

选择四:DiscardOldestPolicy

你查看了一下时间表

放假是周六和周日

今天是周六

于是你选择抛弃周日

最后的周日的任务改为执行老板的工作

你可能感兴趣的:(java学习,java,开发语言)