java 1.8的线程池

java 1.8的线程池

    • FixedThreadPool
    • SingleThreadExecutor
    • CachedThreadPool
    • ScheduledThreadPool

FixedThreadPool

创建一个具有固定线程数的线程池,当创建的线程达到最大数量后,就不再创建新的线程。当所有的线程都在使用时,新提交的任务会阻塞在队列中,直至有线程空闲出来。

package com.dfire.monitor.service.impl.poolTest;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author : baigp
 * create at:  2020/7/22  15:49
 * @description:
 */
public class FixedThreadPoolTest {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Runnable run = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("当前线程名称:" + Thread.currentThread().getName() + " , 当前时间为:" + sdf.format(new Date()));
                    Thread.sleep(3 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        ExecutorService executorService = Executors.newFixedThreadPool(2);
        for (int i = 0 ; i < 10 ; i++){
            executorService.execute(run);
        }
    }
}

打印结果:

当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:14:23
当前线程名称:pool-1-thread-2 , 当前时间为:2020-07-22 16:14:23
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:14:26
当前线程名称:pool-1-thread-2 , 当前时间为:2020-07-22 16:14:26
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:14:29
当前线程名称:pool-1-thread-2 , 当前时间为:2020-07-22 16:14:29
当前线程名称:pool-1-thread-2 , 当前时间为:2020-07-22 16:14:32
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:14:32
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:14:35
当前线程名称:pool-1-thread-2 , 当前时间为:2020-07-22 16:14:35

从打印结果可以看出,一共创建了2个线程,和代码汇总配置的线程数相对应。第三、四个任务提交时,由于两个线程被占用着,所以阻塞在队列中,直至第一、二个任务休眠三秒后,释放了线程,第三、四个任务才开始执行。

SingleThreadExecutor

package com.dfire.monitor.service.impl.poolTest;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author : baigp
 * create at:  2020/7/22  16:03
 * @description:
 */
public class SingleThreadExecutorTest {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Runnable run = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("当前线程名称:" + Thread.currentThread().getName() + " , 当前时间为:" + sdf.format(new Date()));
                    Thread.sleep(3 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        ExecutorService executroService = Executors.newSingleThreadExecutor();
        for (int i = 0 ; i < 10; i++){
            executroService.execute(run);
        }
    }
}

打印结果:

当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:19
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:22
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:25
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:28
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:31
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:34
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:37
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:40
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:43
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:46

可以看出,自始至终只创建了一个线程,后面的任务等待前面的任务执行完毕后才开始执行。

CachedThreadPool

可缓冲线程池。特点:灵活。 没有线程最大数量的限制,当一个任务被提交到线程池时,如果有闲置的线程,则选取一个闲置线程执行,如果没有闲置线程,则创建一个新线程。 对于线程池中的线程,闲置60s后会自动销毁以节省资源。

package com.dfire.monitor.service.impl.poolTest;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author : baigp
 * create at:  2020/7/22  16:30
 * @description:
 */
public class CachedThreadPoolTest {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Runnable run = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("当前线程名称:" + Thread.currentThread().getName() + " , 当前时间为:" + sdf.format(new Date()));
                    Thread.sleep(3 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0 ; i < 1000 ; i++){
            executorService.execute(run);
        }
    }
}

打印结果:

当前线程名称:pool-1-thread-5 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-6 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-4 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-2 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-8 , 当前时间为:2020-07-22 16:32:21
省略中间的打印内容...
当前线程名称:pool-1-thread-997 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-998 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-999 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-1000 , 当前时间为:2020-07-22 16:32:21

可以看出,一共创建了1000个线程。

ScheduledThreadPool

固定线程数上限的线程池,并支持定时和周期性执行任务。

package com.dfire.monitor.service.impl.poolTest;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;

/**
 * @author : baigp
 * create at:  2020/7/22  17:11
 * @description:
 */
public class ScheduledThreadPoolTest {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Runnable run = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("当前线程名称:" + Thread.currentThread().getName() + " , 当前时间为:" + sdf.format(new Date()));
                    Thread.sleep(3 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
        System.out.println("开始执行时间:" + sdf.format(new Date()));
        executorService.scheduleAtFixedRate(run , 3, 5 , TimeUnit.SECONDS);
    }
}

打印结果:

开始执行时间:2020-07-22 17:17:57
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:18:00
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:18:05
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:18:10
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:18:15
。。。

可以看出,executorService 添加线程任务后,首先延迟3s,然后执行run(),而后按照5s/次的频率定时执行run()方法。
注意:如果执行频率由5s/次加快到2s/次,run()方法执行一次需要3s(休眠3s),那么后面的任务会阻塞,等前面的任务执行完后再执行,所用的线程自始至终都是同一个。
执行频率由5s/次加快到2s/次后的打印结果:

开始执行时间:2020-07-22 17:22:47
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:22:50
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:22:53
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:22:56
。。。

你可能感兴趣的:(Java,java,线程池)