java_线程池

线程池

(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);
            }
        }
    }
}

这里写图片描述

方法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()结束");
    }
}

这里写图片描述
添加Thread.sleep(100);后
这里写图片描述

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

方法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);
        }
    }
}

这里写图片描述

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

扫描二维码关注公众号,回复: 5055551 查看本文章

方法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();//关闭线程池
    }
}

这里写图片描述

猜你喜欢

转载自blog.csdn.net/yc_hen/article/details/82315294
今日推荐