手动创建线程池以及线程拒绝策略

由于之前说使用Exectors类创建线程池时候,会造成OOM,建议手动创建线程池。

今天就尝试手动创建线程池,并且介绍它的4中拒绝策略和手动写拒绝策略。

在创建线程池之前,我们先看看线程池创建的构造函数和各个字段的意义。

 

corePoolSize:核心线程数,当线程数未达到核心线程时,新的任务会创建新的线程,即使有线程空闲也会创建新的线程。
maximumPoolSize:线程最大数,当阻塞队列满了之后,就会创建新的线程,达到最大线程数为止。
keepAliveTime:线程空闲时间,当线程空闲时间超过此值,并且线程数大于核心线程,此线程将被回收,以此来保证核心线程数量。
unit:线程空余时间单位。
workQueue:阻塞队列,当任务大于线程数,阻塞队列还未满,就会加入阻塞队列中
threadFactory:管理创建的线程,可以设置线程的名称等属性。
handler:拒绝策略,当阻塞对面已满,线程达到最大线程,就会采用阻塞策略。

知道了各个参数的意义,现在来手动创建线程池。

先创建一个任务,再创建一个线程池。

package test.thread.pool;

public class Task implements Runnable {

    private int i;

    public Task(int i) {
        this.i = i;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " print " + i);
    }

}
package test.thread.pool;

import java.util.concurrent.*;

public class CreateThreadPool {

    public static void main(String[] args) {
        BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<>(2);

        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4,
                60, TimeUnit.SECONDS, blockingQueue,
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        for (int i = 0; i < 10; i++) {
            Task task = new Task(i);
            executor.execute(task);
        }
        executor.shutdown();
    }

}

我们创建了一个核心线程数为2个,最大线程数为4,线程空闲时间为60s,阻塞队列大小为2的线程池,阻塞策略为默认的

AbortPolicy 根据源码可以看到,此种拒绝策略直接抛出rejectedExecution异常,执行结果如下。

pool-1-thread-1 print 0
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task test.thread.pool.Task@6d6f6e28 rejected from java.util.concurrent.ThreadPoolExecutor@135fbaa4[Running, pool size = 4, active threads = 3, queued tasks = 0, completed tasks = 2]
pool-1-thread-2 print 1
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
pool-1-thread-4 print 5
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
pool-1-thread-1 print 2
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
pool-1-thread-3 print 4
	at test.thread.pool.CreateThreadPool.main(CreateThreadPool.java:15)
pool-1-thread-4 print 3
DiscardPolicy 拒绝策略,这种策略是不会做任何处理,不会抛出异常,直接丢弃任务,运行结果如下

import java.util.concurrent.*;

public class CreateThreadPool {

    public static void main(String[] args) {
        BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<>(2);

        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4,
                60, TimeUnit.SECONDS, blockingQueue,
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardPolicy());
        for (int i = 0; i < 10; i++) {
            Task task = new Task(i);
            executor.execute(task);
        }
        executor.shutdown();
    }

}

 

运行结果如下,可以看到没有抛出异常,不做任何处理,直接丢弃了后面的任务。

pool-1-thread-2 print 1
pool-1-thread-3 print 4
pool-1-thread-2 print 2
pool-1-thread-4 print 5
pool-1-thread-1 print 0
pool-1-thread-3 print 3

Process finished with exit code 0
DiscardOldestPolicy 拒绝策略是从队列中移除老的任务,继续执行任务。

 

由运行结果可以看到,前面2,3,6,7任务被丢弃了。

pool-1-thread-1 print 0
pool-1-thread-2 print 1
pool-1-thread-2 print 9
pool-1-thread-1 print 8
pool-1-thread-3 print 4
pool-1-thread-4 print 5

Process finished with exit code 0
CallerRunsPolicy 是不会丢弃任务,直接运行任务的run方法,即使用主线程执行任务,执行结果如下。

 

根据运行结果可以看到,其中有main线程执行任务,因为当线程不足时,会由主线程直接执行run方法。

main print 6
pool-1-thread-4 print 5
pool-1-thread-2 print 1
pool-1-thread-2 print 3
pool-1-thread-1 print 0
pool-1-thread-3 print 4
pool-1-thread-4 print 2
main print 7
pool-1-thread-2 print 8
pool-1-thread-1 print 9

Process finished with exit code 0

 

以上就是线程池的4种拒绝策略,但是并不是很好,还是建议大家手动创建拒绝策略,下面给大家提供一种拒绝策略,供大家参考,当线程拒绝时,还是重复向队列中加,加进去继续让线程处理,执行结果如下。

package test.thread.pool;

import java.util.concurrent.*;

public class CreateThreadPool {

    public static void main(String[] args) {
        BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<>(2);

        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4,
                60, TimeUnit.SECONDS, blockingQueue,
                Executors.defaultThreadFactory(), new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                if (!executor.isShutdown()) {
                    try {
                        executor.getQueue().put(r);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        for (int i = 0; i < 10; i++) {
            Task task = new Task(i);
            executor.execute(task);
        }
        executor.shutdown();
    }

}

 

运行结果可以看到,任务都被执行,并且没有使用主线程运行。

pool-1-thread-1 print 0
pool-1-thread-4 print 5
pool-1-thread-3 print 4
pool-1-thread-2 print 1
pool-1-thread-1 print 2
pool-1-thread-4 print 3
pool-1-thread-1 print 8
pool-1-thread-3 print 6
pool-1-thread-2 print 7
pool-1-thread-4 print 9

Process finished with exit code 0

 

最后再贴上更改线程名称等属性的代码

package test.thread.pool;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class CreateThreadPool {

    static class NameThreadFactory implements ThreadFactory {

        private AtomicInteger count = new AtomicInteger();
        private String name;

        public NameThreadFactory(String name) {
            this.name = name + "-";
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r, name + count.incrementAndGet());
            if (t.isDaemon()) {
                t.setDaemon(false);
            }
            if (t.getPriority() != Thread.NORM_PRIORITY) {
                t.setPriority(Thread.NORM_PRIORITY);
            }
            return t;
        }
    }

    public static void main(String[] args) {
        BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<>(2);

        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4,
                60, TimeUnit.SECONDS, blockingQueue,
                new CreateThreadPool.NameThreadFactory("test-thread-pool"), new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                if (!executor.isShutdown()) {
                    try {
                        executor.getQueue().put(r);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        for (int i = 0; i < 10; i++) {
            Task task = new Task(i);
            executor.execute(task);
        }
        executor.shutdown();
    }

}

 

运行结果如下,可以看到线程名称变化

test-thread-pool-1 print 0
test-thread-pool-2 print 1
test-thread-pool-2 print 3
test-thread-pool-1 print 2
test-thread-pool-2 print 6
test-thread-pool-1 print 7
test-thread-pool-2 print 8
test-thread-pool-1 print 9
test-thread-pool-3 print 4
test-thread-pool-4 print 5

Process finished with exit code 0

以上就是手动创建线程,以及创建线程策略和线程属性的例子,如有不对的地方,还请指出,谢谢

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Java中手动创建符合阿里规范的线程池,您可以使用`java.util.concurrent.ThreadPoolExecutor`类进行自定义配置。以下是一个示例: ```java import java.util.concurrent.*; public class Main { public static void main(String[] args) { int corePoolSize = 5; // 核心线程数 int maxPoolSize = 10; // 最大线程数 long keepAliveTime = 60; // 线程空闲时间(秒) int queueCapacity = 100; // 阻塞队列容量 ThreadFactory threadFactory = Executors.defaultThreadFactory(); // 线程工厂 RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.AbortPolicy(); // 拒绝策略 // 创建线程池 ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, new ArrayBlockingQueue<>(queueCapacity), threadFactory, rejectedExecutionHandler ); // 提交任务给线程池 for (int i = 0; i < 10; i++) { Runnable worker = new WorkerThread("Task " + (i + 1)); executor.execute(worker); } // 关闭线程池 executor.shutdown(); try { if (!executor.awaitTermination(10, TimeUnit.SECONDS)) { executor.shutdownNow(); } } catch (InterruptedException e) { executor.shutdownNow(); Thread.currentThread().interrupt(); } System.out.println("所有任务已完成"); } } class WorkerThread implements Runnable { private String taskName; public WorkerThread(String taskName) { this.taskName = taskName; } @Override public void run() { System.out.println(Thread.currentThread().getName() + " 开始执行任务: " + taskName); // 执行任务的逻辑代码 System.out.println(Thread.currentThread().getName() + " 完成任务: " + taskName); } } ``` 在上面的示例中,我们手动创建了一个线程池,其中包括了一些符合阿里规范的配置: - 核心线程数为5,最大线程数为10; - 线程空闲时间为60秒,超过空闲时间的线程将被回收; - 阻塞队列容量为100,超过容量的任务将被拒绝执行; - 使用默认的线程工厂和拒绝策略; - 在关闭线程池时,使用`awaitTermination()`方法等待最多10秒钟,如果超时仍有任务未完成,则强制关闭线程池。 请注意,这只是一个示例,您可以根据自己的需求进行适当的调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值