创建线程的方式与过程(代码解析+对比)

创建线程的方式

继承Thread类(extends)
实现Runnable接口(implements)
实现Callable接口+Future Task(可以拿到返回结果,可处理异常)
线程池:Executors/ThreadPoolExecutor

线程池工作流程

  • 线程池创建准备好corePoolSize大小的核心线程准备
  • 任务来了先试用核心线程
  • core满了,将再进来的任务放到阻塞队列中等候
  • 阻塞队列满了,直接开启新的线程(不超过max数量)
  • 非核心线程会在keepAliveTime后自动销毁
  • 超过max数量的任务执行拒绝策略(abortPolicy、discardPolicy、discardOldPolicy、callerRunsPolicy)
  • 所有的线程创建都是在线程工厂中完成

Executors()

newFixedThreadPool();固定大小
newCachedThreadPool();无限大小
newSingleThreadExecutor();单线程
scheduledThreadExecutor();定长定时

*不建议使用(有内存泄漏风险)

ThreadPoolExcutor()

参数

int corePoolSize,
int maximumPoolSize
long keepAliveTime
TimeUnit unit
BlockingQueue workQueue
ThreadFactory threadFactory
RejectedExecutionHandler handler(策略模式)context+RejectedExecutionHandlerInterface+具体拒绝实现

代码实现

package com.example.demo.controller;


import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.*;

/**
 * @author Adam
 * @version 1.0
 * @description 线程的创建
 * @date 2022/5/14
 */
public class TestThread {
    public static void main(String[] args) throws Exception {
//        1.继承Thread类
        Thread0 thread0 = new Thread0();
        thread0.run();
//        2.实现Runnable接口
        Runnable0 runnable0 = new Runnable0();
        runnable0.run();
//        3.实现Callable接口
        Callable0 callable0 = new Callable0();
        callable0.call();
//        4.线程池
//            4.1Executors
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        System.out.println("4.1Executors创建线程池");
        executorService.submit(runnable0);
        executorService.shutdown();
//            4.2ThreadPoolExecutor
/**
 *           int corePoolSize,
 *           int maximumPoolSize,
 *           long keepAliveTime,
 *           TimeUnit unit,
 *           BlockingQueue<Runnable> workQueue,
 *           ThreadFactory threadFactory,
 *           RejectedExecutionHandler handler
 */
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,
                                                                    20,
                                                                    100,
                                                                    TimeUnit.MILLISECONDS,
                                                                    new LinkedBlockingDeque<>(10)
                                                            );
        //LinkedBlockingDeque和LinkedBlockingQueue的区别:
        //线程安全以及阻塞等待的实现基本没有区别,两个阻塞队列基本可以通用(LinkedBlockingDueue用作栈时除外)。
        // 不同:一个是底层数据结构的细微区别,LinkedBlockingQueue是单向链表,而LinkedBlockingDueue则是双向链表;
        //       S另一个是重入锁的使用有些区别,LinkedBlockingDueue不论出入队都使用的是同一个锁对象,而LinkedBlockingQueue的出入队锁是分开的。
        threadPoolExecutor.execute(() -> {
            System.out.println("4.2ThreadPoolExecutor创建线程池");
            ThreadMXBean bean = ManagementFactory.getThreadMXBean();
            System.out.println("当前线程总数为:" + bean.getThreadCount());
        });
        threadPoolExecutor.shutdown();

    }

    /**
     * 继承Thread类
     */
    private static class Thread0 extends Thread {
        @Override
        public void run() {
            System.out.println("1.继承Thread类");
            System.out.println("当前线程ID:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            System.out.println("------------------------------------");
        }
    }

    /**
     * 实现Runnable接口
     */
    private static class Runnable0 implements Runnable {
        @Override
        public void run() {
            System.out.println("2.实现Runnable接口");
            System.out.println("当前线程ID:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("运行结果:" + i);
            System.out.println("------------------------------------");
        }
    }

    /**
     * 实现Callable接口
     */
    private static class Callable0 implements Callable {
        @Override
        public Integer call() throws Exception {
            System.out.println("3.实现Callable接口");
            System.out.println("当前线程ID:" + Thread.currentThread().getId());
            int i = 20 / 5;
            System.out.println("运行结果:" + i);
            System.out.println("------------------------------------");
            return i;
        }
    }
}

各方式优缺点对比

实现方式优点缺点
继承Thread类编写简单,使用 this 即可获得当前线程不能再继承其他父类
实现Runnable接口可继承其他类不能处理异常和获取处理结果
实现Callable接口+Future Task可以继承其他类,可拿到返回结果,可处理常异步编排实现复杂
Executors创建线程池减少创建销毁线程开销内存泄漏隐患,易OOM
ThreadPoolExecutor创建线程池减少创建销毁线程开销需要手动关闭线程池避免资源浪费
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Adam`南帝·梁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值