Java 线程池的创建——7种方法

2年前 (2022) 程序员胖胖胖虎阿
318 0 0

线程池的创建分为两大类方法

  • 通过Executors自动创建
  • 通过ThreadPoolExecutor手动创建

Executors创建线程池的方法——6种

  1. newFixedThreadPool:创建一个固定大小的线程池
public class ThreadPool1 {
    public static void main(String[] args) {
        //1.创建一个大小为5的线程池
        ExecutorService threadPool= Executors.newFixedThreadPool(5);
        //2.使用线程池执行任务一
        for (int i=0;i<5;i++){
            //给线程池添加任务
            threadPool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("线程名"+Thread.currentThread().getName()+"在执行任务1");
                }
            });
        }
        //2.使用线程池执行任务二
        for (int i=0;i<8;i++){
            //给线程池添加任务
            threadPool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("线程名"+Thread.currentThread().getName()+"在执行任务2");
                }
            });
        }

    }
}

结果:
Java 线程池的创建——7种方法

  1. newCachedThreadPool:带缓存的线程池,适用于短时间有大量任务的场景,但有可能会占用更多的资源;线程数量随任务量而定。
public class ThreadPool3 {
    public static void main(String[] args) {
        //创建线程池
        ExecutorService service= Executors.newCachedThreadPool();
        //有50个任务
        for(int i=0;i<50;i++){
            int finalI = i;
            service.submit(()->{
                System.out.println(finalI +"线程名"+Thread.currentThread().getName());//线程名有多少个,CPU就创建了多少个线程
            });
        }
    }
}

结果:
执行了两次:一次有18个线程,一次有19个线程;线程的数量由cpu根据任务量而定。

  1. newSingleThreadExecuto:创建单个线程的线程池

创建单个线程的线程池?为啥不直接创个线程?

  • 线程池的优点:
  • 1.复用线程:不必频繁创建销毁线程
  • 2.也提供了任务队列和拒绝策略
public class ThreadPool4 {
    public static void main(String[] args) {
        ExecutorService service= Executors.newSingleThreadExecutor();
        for (int i=0;i<5;i++){
            int finalI = i;
            service.submit(()->{
                System.out.println(finalI +"线程名"+Thread.currentThread().getName());//CPU只创建了1个线程,名称始终一样
            });
        }
    }
}

结果:
Java 线程池的创建——7种方法

  1. newSingleThreadScheduledExecutor:创建执行定时任务的单个线程的线程池
public class ThreadPool5 {
    public static void main(String[] args) {
        ScheduledExecutorService service= Executors.newSingleThreadScheduledExecutor();
        System.out.println("添加任务:"+ LocalDateTime.now());
        service.schedule(new Runnable() {

                @Override
                public void run() {
                    System.out.println("执行任务:"+LocalDateTime.now());
                }
            },3,TimeUnit.SECONDS);//推迟3秒执行任务
    }
}

结果:时间相差 3s
Java 线程池的创建——7种方法

  1. newScheduledThreadPool:创建执行定时任务的线程池
/**
 * 创建执行定时任务的线程池
 */
public class ThreadPool6 {
    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(5);//5个线程
        System.out.println("添加任务:" + LocalDateTime.now());
        //once(service);
        many(service);
    }
    /**
     * 执行一次的定时任务
     */
    public static void once(ScheduledExecutorService service) {
        service.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务:"+ LocalDateTime.now());
            }
        },3, TimeUnit.SECONDS);//推迟3秒执行
    }
}

执行一次的定时任务 的结果:

Java 线程池的创建——7种方法
当执行多次的定时任务——scheduleWithFixedDelay

//2.推迟3秒执行;上一次任务结束2s后,下一个任务开始执行
        service.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务:"+ LocalDateTime.now()+"线程名"+Thread.currentThread().getName());
                try {
                    Thread.sleep(1000*2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },3,2,TimeUnit.SECONDS);//间隔时间成了4s;因为线程休眠了2s

Java 线程池的创建——7种方法
当执行多次的定时任务——scheduleAtFixedRate

//1.推迟3秒执行;上一次任务开始2s后,下一个任务开始执行
       service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务:"+ LocalDateTime.now()+"线程名"+Thread.currentThread().getName());
                try {
                    //1.间隔时间>执行时间;以间隔时间为准
                    Thread.sleep(100);
                    //2.执行时间>间隔时间;以执行时间为准
                    Thread.sleep(1000*3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },3,2,TimeUnit.SECONDS);

1.间隔时间2s>执行时间0.1s;以间隔时间为准
Java 线程池的创建——7种方法

2.执行时间3s>间隔时间2s;以执行时间为准
Java 线程池的创建——7种方法

  1. newWorkStealingPool:根据当前设备的配置自动生成线程池
public class ThreadPool7 {
    public static void main(String[] args) {
        ExecutorService service= Executors.newWorkStealingPool();
        for(int i=0;i<50;i++){
            int finalI = i;
            service.submit(()->{
                System.out.println(finalI +"线程名"+Thread.currentThread().getName());//线程名有多少个,CPU就创建了多少个线程
            });
        }
        //创建的为守护线程,JVM不会等待守护线程结束
        while (!service.isTerminated()){

        }
    }
}

根据自身电脑配置决定创建的线程数目

ThreadPoolExecutor——7.手动创建线程池

public class ThreadPool9 {
    public static void main(String[] args) {
        //线程工厂
        ThreadFactory factory=new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread=new Thread(r);

                return thread;
            }
        };
        //手动创建线程池
        ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(2), factory,
                //1.提示异常,拒绝执行多余的任务
               // new ThreadPoolExecutor.AbortPolicy()

                //2.忽略堵塞队列中最旧的任务
                //new ThreadPoolExecutor.DiscardOldestPolicy()

                //3.忽略最新的任务
                //new ThreadPoolExecutor.DiscardPolicy()

                //4.使用调用该线程池的线程来执行任务
                //new ThreadPoolExecutor.CallerRunsPolicy()

                //5.A自定义拒绝策略
                new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.out.println("拒绝策略");
            }
        }
        );
        //任务
        for (int i=0;i<7;i++){
            int finalI=i;
            threadPoolExecutor.submit(()->{
                try {
                    Thread.sleep(finalI*100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"任务名"+finalI);
            });
        }
        
    }
}

Java 线程池的创建——7种方法
7种参数分别是:

  • 核心(最少)线程数

  • 最大线程数

  • 闲置可存活时间

  • 描述(闲置可存活时间)的单位

  • 任务队列

  • 线程工厂

  • 拒绝策略有5种:

             //1.提示异常,拒绝执行多余的任务
            // new ThreadPoolExecutor.AbortPolicy()
            
            //2.忽略堵塞队列中最旧的任务
             //new ThreadPoolExecutor.DiscardOldestPolicy()
    
             //3.忽略最新的任务
             //new ThreadPoolExecutor.DiscardPolicy()
    
             //4.使用调用该线程池的线程来执行任务
             //new ThreadPoolExecutor.CallerRunsPolicy()
    
             //5.自定义拒绝策略
             new RejectedExecutionHandler()
    
版权声明:程序员胖胖胖虎阿 发表于 2022年9月28日 上午3:48。
转载请注明:Java 线程池的创建——7种方法 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...