Java中的线程和线程池

发布时间:2024年01月17日

目录

一、什么是线程,什么是线程池

二、单个线程如何使用(线程的几种使用方法)

三、单线程的好处和坏处,频繁使用单线程会导致什么问题?

四、使用线程池的好处

五、线程池的核心参数解析

六、如何使用线程池(线程池的使用方法)

七、线程池工具类


一、什么是线程,什么是线程池

在Java中,线程是用于执行程序中独立任务的执行单元。它允许多个任务同时执行,从而提高程序的并发性。线程池是线程的管理机制,它维护着一个线程集合,可以重复利用这些线程来执行多个任务。

二、单个线程如何使用(线程的几种使用方法)

1.继承Thread类:创建一个类继承自Thread类,并重写其run()方法,在该方法中定义线程要执行的任务。

public class MyThread extends Thread {
    @Override
    public void run() {
        // 线程执行的任务逻辑
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start(); // 启动线程
    }
}

2.实现Runnable接口:创建一个类实现Runnable接口,并实现其中的run()方法,在该方法中定义线程要执行的任务。

public class MyRunnable implements Runnable {

????@Override

????public void run() {

????????// 线程执行的任务逻辑

????}

}



public class Main {

????public static void main(String[] args) {

????????MyRunnable runnable = new MyRunnable();

????????Thread thread = new Thread(runnable);

????????thread.start(); // 启动线程

????}

}

3.使用匿名内部类:通过创建一个继承Thread类或实现Runnable接口的匿名内部类,来定义线程要执行的任务。

public class Main {

????public static void main(String[] args) {

????????Thread thread = new Thread(new Runnable() {

????????????@Override

????????????public void run() {

????????????????// 线程执行的任务逻辑

????????????}

????????});

????????thread.start(); // 启动线程

????}

}

三、单线程的好处和坏处,频繁使用单线程会导致什么问题?

单线程的好处是简单易用,适用于一些简单的任务,不需要考虑线程之间的同步和协作。

然而,频繁使用单线程会导致程序的执行效率较低,因为任务需要按照顺序依次执行,无法利用多核处理器的优势。

四、使用线程池的好处

提高性能:线程池可以重用线程,避免线程的频繁创建和销毁,从而节省系统资源。

提供线程管理和调度:线程池可以自动管理线程的生命周期,并提供线程的调度和监控功能。使用线程池时,一般情况下不需要手动关闭线程。线程池会自动管理线程的生命周期,并在任务执行完成后将线程释放回线程池以供重用。

控制并发度:线程池可以限制并发执行的线程数量,防止系统资源被过度占用。

五、线程池的核心参数解析

核心线程数(corePoolSize):线程池中保持的常驻线程数量。

最大线程数(maximumPoolSize):线程池允许创建的最大线程数。

队列容量(workQueue):用于存放等待执行的任务的队列。

线程空闲时间(keepAliveTime):当线程池中线程数量超过核心线程数时,多余的空闲线程的存活时间。

线程工厂(threadFactory):用于创建新线程的工厂。

拒绝策略(rejectedExecutionHandler):当线程池和任务队列都满了,无法处理新的任务时,使用的策略。

六、如何使用线程池(线程池的使用方法)

创建线程池:通过ThreadPoolExecutor类的构造函数或Executors工具类提供的静态方法创建线程池。

提交任务:通过execute()方法提交任务给线程池执行。

关闭线程池:通过调用线程池的shutdown()或shutdownNow()方法来关闭线程池。

以下是简单的示例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    public static void main(String[] args) {
        // 创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(5);

        // 提交任务给线程池执行
        for (int i = 0; i < 10; i++) {
            final int task = i;
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Task " + task + " is being executed.");
                    // 执行任务的逻辑代码
                }
            });
        }

        // 关闭线程池
        executor.shutdown();
    }
}

七、线程池工具类

这里给大家提供一个可直接使用的线程池工具类

/**
 * 线程池管理类(工具类)
 *
 */
public class ThreadPoolManager {

    /**
     * 根据cpu的数量动态的配置核心线程数和最大线程数
     */
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

    /**
     * 核心线程数 = CPU核心数 + 1
     * IO密集型:2CPU,计算密集型:CPU + 1
     */
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;

    /**
     * 线程池最大线程数 = CPU核心数 * 2 + 1
     */
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;

    /**
     * 非核心线程闲置时超时时间
     */
    private static final int KEEP_ALIVE = 60;
    /**
     * 唯一实例
     */
    public static ThreadPoolManager instance = newInstance();
    /**
     * 线程池的对象
     */
    private ThreadPoolExecutor executor;
    /**
     * map:存储任务
     */
    private Map<Long, Runnable> taskMap = new HashMap<Long, Runnable>();

    /**
     * 要确保该类只有一个实例对象,避免产生过多对象消费资源,所以采用单例模式
     */
    private ThreadPoolManager() {
    }

    /**
     * 获取实例
     *
     * @return 当前类实例
     */
    private static ThreadPoolManager newInstance() {
        ThreadPoolManager instance = new ThreadPoolManager();
        instance.executor = instance.newPool();
        return instance;
    }

    /**
     * 新建线程池
     * corePoolSize:核心线程数
     * maximumPoolSize:线程池所容纳最大线程数(workQueue队列满了之后才开启)
     * keepAliveTime:非核心线程闲置时间超时时长
     * unit:keepAliveTime的单位
     * workQueue:等待队列,存储还未执行的任务
     * threadFactory:线程创建的工厂
     * handler:异常处理机制
     *
     * @return 线程池
     */
    private ThreadPoolExecutor newPool() {
        return new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(ThreadPoolConstants.THREAD_NUM),
                CustomDefaultThreadFactory.newDefaultThreadFactory("MetaDataThreadPool"),
                new ThreadPoolExecutor.AbortPolicy());
    }

    /**
     * 开启一个无返回结果的线程
     *
     * @param r the r
     */
    public void execute(Runnable r) {
        // 把一个任务丢到了线程池中
        executor.execute(r);
    }

    /**
     * 开启一个无返回结果的线程
     *
     * @param taskId the task id
     * @param r the r
     */
    public void execute(Long taskId, Runnable r) {
        // 把一个任务丢到了线程池中
        executor.execute(r);
        // 并加入map中
        taskMap.put(taskId, r);
    }

    /**
     * 开启一个有返回结果的线程
     *
     * @param <T> the type parameter
     * @param r the r
     * @return future future
     */
    public <T> Future<T> submit(Callable<T> r) {
        // 把一个任务丢到了线程池中
        return executor.submit(r);
    }

    /**
     * 通过jobPublish的id关闭线程
     *
     * @param id the id
     */
    public void cancel(Long id) {
        if (taskMap.containsKey(id)) {
            if (taskMap.get(id) != null) {
                executor.getQueue().remove(taskMap.get(id));
            }
        }
    }

    /**
     * 把任务移除等待队列
     *
     * @param r the r
     */
    public void cancel(Runnable r) {
        if (r != null) {
            executor.getQueue().remove(r);
        }
    }
}

使用示例:

ThreadPoolManager.instance.execute(new BaseRunnable() {
                @Override
                public void work() {
                    // 业务方法
                }
           });

文章来源:https://blog.csdn.net/MrBInsomnia/article/details/135644975
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。