Java线程池

线程池的核心类- ThreadPoolExecutor

ThreadPoolExecutor extends AbstractExecutorService

Executors

ExecutorService

构造方法
ThreadPoolExecutor(int corePoolSize, //  核心线程数
                   int maximumPoolSize, // 最大线程数
                   long keepAliveTime, // 空闲时间
                   TimeUnit unit, // 时间单位
                   BlockingQueue<Runnable> workQueue, // 任务队列
                   ThreadFactory threadFactory, // 线程工厂
                   RejectedExecutionHandler handler // 拒绝策略
                   )
任务队列
BlockingQueue接口的实现类
1. SynchronousQueue2. LinkedBlockingQueue3. ArrayBlockingQueue4. LinkedTransferQueue

线程池重要的方法

  • execute
execute(Runnable command)
1. 充当核心线程运行
2. 放入任务队列,需要double-check
3. 如果放不进任务队列,尝试运行新线程,失败了就拒绝
  • addWorker
addWorker(Runnable firstTask, boolean core)
根据核心线程数和最大线程数判断是否添加新的线程
第一个参数是execute提交的任务
第二个参数是核心线程或者最大线程

  • submit
submit(Runnable task)
未来能得到返回值

创建线程池

ThreadPoolExecutor自定义

ThreadPoolExecutor executor = new ThreadPoolExecutor(
            5,
            10,
            10,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(10),
            new ThreadPoolExecutor.CallerRunsPolicy());

Executor创建

ExecutorService p1 = Executors.newFixedThreadPool(3);
ScheduledExecutorService p2 = Executors.newSingleThreadScheduledExecutor();
ExecutorService p3 = Executors.newSingleThreadExecutor();
ExecutorService p4 = Executors.newCachedThreadPool();
ScheduledExecutorService p5 = Executors.newScheduledThreadPool(5);
ExecutorService p6 = Executors.newWorkStealingPool(2);

多线程异常处理

  • 例子 – 无法捕获异常
public class MultiThreadsException {
    public static void main(String[] args) {
        Thread thread = new Thread(new ThrowsExceptionRun());
        try {
            thread.start();
        }catch (Exception e){
            System.out.println("捕获到异常。。。");
        }
    }

    static class ThrowsExceptionRun implements Runnable {
        @Override
        public void run() {
            int dividend = 25;
            int divisor = 3;
            while (divisor >=0){
                System.out.println(dividend + " 和 " + divisor + "相除结果是: " + dividend / divisor);
                divisor --;
            }
            System.out.println("结束运算。。。");
        }
    }
}

// 不能捕获异常
原因: 
Thread所创建的线程需要在自己的逻辑中,即run方法中捕获异常
不能抛出异常给外界的线程

底层原因是Thread默认使用uncaughtException()方法空处理,虚拟机会忽略该方法之后的抛出异常

多线程异常处理

1.ThreadRunnable的run方法中try-catch
2. 使用Callable接口创建线程,通过get() 方法获取异常
3. 使用线程池Executor设置改写的ExceptionHandler来处理线程异常
try-catch
public class MultiThreadsException {
    public static void main(String[] args) {
        Thread thread = new Thread(new ThrowsExceptionRun());
        try {
            thread.start();
        }catch (Exception e){
            System.out.println("捕获到异常。。。");
        }
    }

    static class ThrowsExceptionRun implements Runnable {
        @Override
        public void run() {
            int dividend = 25;
            int divisor = 3;
            while (divisor >=0){
                try {
                    System.out.println(dividend + " 和 " + divisor + "相除结果是: " + dividend / divisor);
                }catch (Exception e){
                    System.out.println("哟,有异常了");
                    throw e;
                }
                divisor --;
            }
            System.out.println("结束运算。。。");
        }
    }
}

Callable接口

public class MultiThreadsException {
    public static void main(String[] args) {
        Callable<String> getCallThread = new ThrowsExceptionCall();
        FutureTask<String> futureTask = new FutureTask<>(getCallThread);
        Thread thread = new Thread(futureTask);
        thread.start();
        try {
            TimeUnit.SECONDS.sleep(3);
            String s = futureTask.get();
            System.out.println(s);
        } catch (Exception e) {
            System.out.println("异常捕获到了。。。");
            e.printStackTrace();
        }
    }

    static class ThrowsExceptionCall implements Callable<String> {

        @Override
        public String call() throws Exception {
            String fullString = "I'm OK,do not worry about me";
            return fullString.substring(3, 60); // 下标越界异常
        }
    }

Executor改写UncaughtExceptionHandler接口

public class ExecutorCatchException {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService service = Executors.newCachedThreadPool(new SuccessCatchThreadExceptionFactory());
        service.execute(new ThrowsExceptionRun());
        service.awaitTermination(3, TimeUnit.SECONDS);
        service.shutdown();
    }
}
// 线程工厂 设置了异常处理器
class SuccessCatchThreadExceptionFactory implements ThreadFactory {
    @Override
    public Thread newThread(Runnable runnable) {
        Thread thread = new Thread(runnable);
        thread.setUncaughtExceptionHandler(new SuccessCatchThreadExceptionHandler());
        return thread;
    }
}
// 异常处理器
class SuccessCatchThreadExceptionHandler implements Thread.UncaughtExceptionHandler{
    @Override
    public void uncaughtException(Thread thread, Throwable e) {
        System.out.println(thread.getName() + "抛出了异常,请看: " + e.getMessage());
    }
}
// 任务
class ThrowsExceptionRun implements Runnable {
    @Override
    public void run() {
        int dividend = 25;
        int divisor = 3;
        while (divisor >= 0) {
            System.out.println(dividend + " 和 " + divisor + "相除结果是: " + dividend / divisor);
            divisor--;
        }
        System.out.println("结束运算。。。");
    }
}

多线程定时任务

java定时器Timer类

package com.chauncy.timers;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Chauncy Jin
 * Tool: Timer启动多个任务,其中一个出现异常,其余任务也会异常终止
 * @date 2021/12/12
 */

public class TestMultiTimerTask {
   static volatile  AtomicInteger decreaseInteger = new AtomicInteger(8);
    public static void main(String[] args) {

        Timer timer = new Timer();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
        timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        System.out.println("我是第一个TimerTask线程,当前时间为: " + dateFormat.format(new Date()));
                    }
                }, 2000, 5000);

        timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        System.out.println("我是第二个TimerTask线程,当前时间为: " + dateFormat.format(new Date()));
                        int de = TestMultiTimerTask.decreaseInteger.decrementAndGet();
                        int i = (100 / de);
                    }
                }, 3001, 1000);
    }
}

  • 原理
优先级任务队列 TaskQueue queue = new TaskQueue()
线程    TimerThread thread = new TimerThread(queue);

启动的线程会等待任务 -- queue.wait();
放任务到优先级队列 queue.add(task);
取任务  task = queue.getMin();
执行 task.run();

schedule(TimerTask task, long delay, long period) ->
sched(task, System.currentTimeMillis()+delay, -period) ->
sched(TimerTask task, long time, long period) -> 
task.nextExecutionTime = time
task.period = period;
task.state = TimerTask.SCHEDULED;
queue.add(task); -> queue[++size] = task; fixUp(size);


loop线程
队列为空时等待 queue.wait();
取任务 task = queue.getMin();
是否执行 taskFired = (executionTime<=currentTime)
queue.rescheduleMin(加上period时间) -> queue[1].nextExecutionTime = newTime;
执行任务 task.run();
    

ScheduledExecutorService运行多任务

package com.chauncy.timers;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;

import java.util.TimerTask;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * @author Chauncy Jin
 * Tool: 第二个任务出现异常不会影响第一个任务的运行
 * @date 2021/12/12
 */

public class ScheduleExecutorServiceTest {
    static volatile AtomicInteger decreaseInteger = new AtomicInteger(8);
    public static void main(String[] args) {
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(4, new BasicThreadFactory.Builder()
                .namingPattern("example-schedule-pool-%d").daemon(true).build());

        //ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);

        executor.scheduleAtFixedRate(() -> System.out.println( Thread.currentThread().getName() + "第一次延迟2s执行,以后每隔5s执行一次"),
                2000,
                5000,
                TimeUnit.MILLISECONDS);

        executor.schedule(() -> {
            System.out.println(Thread.currentThread().getName()+ " 每隔3s执行");
        },3,TimeUnit.SECONDS);

        executor.scheduleWithFixedDelay(() -> System.out.println(Thread.currentThread().getName() + " 延迟1s执行。。。"),1,1,TimeUnit.SECONDS);

        executor.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " 第一次延迟3s执行,以后每隔1s执行一次");
                int de = ScheduleExecutorServiceTest.decreaseInteger.decrementAndGet();
                try {
                    int i = (100 / de);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        },3001,1000, TimeUnit.MILLISECONDS);


        while (true){
            // main线程活着
        }
    }
}

Spring-Task任务调度工具

Quartz大数据任务调度框架

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java线程池是一种用于管理和复用线程的机制,它可以提高多线程应用程序的性能和效率。线程池中的线程可以被重复使用,避免了频繁创建和销毁线程的开销。 在Java中,线程池可以通过`ExecutorService`接口来创建和管理。线程池中的线程可以执行提交给它的任务,并且可以根据需要自动创建新的线程或销毁闲置的线程。 嵌套线程池是指在一个线程池中创建另一个线程池。这种情况通常发生在需要处理一些复杂的任务,其中每个任务本身也需要使用线程池来执行。 下面是一个示例代码,演示了如何在Java中嵌套使用线程池: ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class NestedThreadPoolExample { public static void main(String[] args) { // 创建外层线程池 ExecutorService outerThreadPool = Executors.newFixedThreadPool(5); // 提交任务给外层线程池 outerThreadPool.execute(() -> { // 创建内层线程池 ExecutorService innerThreadPool = Executors.newFixedThreadPool(3); // 提交任务给内层线程池 innerThreadPool.execute(() -> { // 内层线程池执行的任务 System.out.println("Inner thread pool task executed"); }); // 关闭内层线程池 innerThreadPool.shutdown(); }); // 关闭外层线程池 outerThreadPool.shutdown(); } } ``` 在上面的示例中,我们首先创建了一个外层线程池`outerThreadPool`,它使用`Executors.newFixedThreadPool()`方法创建了一个固定大小的线程池。然后,我们向外层线程池提交了一个任务,该任务在执行时创建了一个内层线程池`innerThreadPool`,并向内层线程池提交了一个任务。最后,我们分别关闭了内层线程池和外层线程池

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值