欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java_线程池

程序员文章站 2022-05-04 17:58:24
...

线程池

(1)如果每个任务都需要创建线程对象,内存开销大
(2)方便管理线程对象

线程池的原理

就是一些线程的集合,线程的状态不是死亡状态,当线程池接收到外面的任务时,线程池会查看是否有空闲线程,若有,就会将任务分配给它,任务处于等待队列中

线程池类型:ExecutorService
Executors里提供了多个静态方法来获取线程池对象

Executors的四个常用方法

方法1

static ExecutorService newSingleThreadExecutor()
获取单个线程的线程池对象,内部维护了一个*队列,用来存储任务

/**
 * 单个线程的线程池,维护了一个*队列
 */
public class ThreadPoolDemo01 {
    public static void main(String[] args) {
        /*获取线程池对象*/
        ExecutorService pool = 
                Executors.newSingleThreadExecutor();
        /*创建5个任务*/
        Task r1 = new Task("A");
        Task r2 = new Task("B");
        Task r3 = new Task("C");
        Task r4 = new Task("D");
        Task r5 = new Task("E");
        /*
         * 此线程池:会按照添加任务的顺序执行任务
         * */
        pool.execute(r1);
        pool.execute(r2);
        pool.execute(r3);
        pool.execute(r4);
        pool.execute(r5);
        System.out.println("main()结束");

    }
}
/**
 * 添加任务Task
 */
 class Task implements Runnable{
    private String name;

    public Task(String name) {
        this.name = name;
    }
    public void run() {
        synchronized (Task.class) {
            for(int i=1;i<=3;i++){
                System.out.println(name+":"+i);
            }
        }
    }
}

java_线程池

方法2

static ExecutorService newFixedThreadPool(int nThreads)
创建一个固定数量(nThreads)线程的线程池

public class ThreadPoolDemo02 {
    public static void main(String[] args) {
        ExecutorService pool = 
                Executors.newFixedThreadPool(2);
        Task r1 = new Task("A");
        Task r2 = new Task("B");
        Task r3 = new Task("C");
        Task r4 = new Task("D");
        Task r5 = new Task("E");
        /*
         * 此线程池:会按照添加任务的顺序执行任务
         * 但是,如果任务体较短,控制台的输出打印顺序可能会乱序
         * 可以使用Thread.sleep()来减缓输出打印的速度
         * */
        pool.execute(r1);
        pool.execute(r2);
        pool.execute(r3);
        pool.execute(r4);
        pool.execute(r5);
        System.out.println("main()结束");
    }
}

java_线程池
添加Thread.sleep(100);后
java_线程池

两个线程对象并发执行任务,执行完后,接取新任务继续执行

方法3

static ExecutorService newCachedThreadPool()
创建一个可以根据需求来创建新线程的线程池对象,若有可重用的,会优先使用
当添加任务进入线程池时,有空线程,线程池管理器将此任务分配给一个空线程

public class ThreadPoolDemo03 {
    public static void main(String[] args) {
        ExecutorService pool = 
                Executors.newCachedThreadPool();
        Runnable r1 = new Run(1);
        Runnable r2 = new Run(2);
        Runnable r3 = new Run(3);
        Runnable r4 = new Run(4);
        Runnable r5 = new Run(5);

        pool.execute(r1);
        pool.execute(r2);
        pool.execute(r3);
        pool.execute(r4);

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        /*当添加任务进入线程池时,有空线程,线程池管理器将此任务分配给一个空线程*/
        pool.execute(r5);

    }
}
class Run implements Runnable{

    private int version;
    public Run(){}
    public Run(int version){
        this.version = version;
    }

    @Override
    public void run() {

        for(int i=1;i<=3;i++){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(
                    Thread.currentThread().getName()+
                    "任务"+version+":"+i);
        }
    }
}

java_线程池

可以看到上述线程池对象一共创建了4个线程对象,而非5个。
前4个任务是并发执行的,每个任务都需要一个线程对象来执行,最后一个任务延迟了5秒后线程池对象才接收到,此时线程池中存在空闲的线程对象,故不再产生新的线程对象,将任务随机分配给其中一个空闲线程对象。

方法4

static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个线程池,可以进行设置延迟或定时执行任务

public class ThreadPoolDemo04 {
    public static void main(String[] args) {
        /*延时是ScheduledExecutorService自己独有的方法,父接口ExecutorService没有延时的方法*/
        ScheduledExecutorService pool = 
                Executors.newScheduledThreadPool(2);
        Runnable r1 = new Run(1);
        Runnable r2 = new Run(2);
        Runnable r3 = new Run(3);
        Runnable r4 = new Run(4);
        Runnable r5 = new Run(5);

        pool.execute(r1);
        pool.execute(r2);
        pool.execute(r3);
        pool.execute(r4);
        pool.schedule(r5, 15, TimeUnit.SECONDS);//延迟15s

        pool.shutdown();//关闭线程池
    }
}

java_线程池