前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线程初始化与线程池详解

线程初始化与线程池详解

原创
作者头像
一个风轻云淡
发布2024-05-01 18:50:00
1560
发布2024-05-01 18:50:00
举报
文章被收录于专栏:java学习javajava学习java

一、线程初始化方式

在Java中,线程的初始化主要有四种方式:

1. 继承Thread类

通过继承Thread类并重写其run()方法,可以创建并启动一个线程。这种方式简单直观,但Java不支持多继承,因此如果一个类已经继承了其他类,就不能再继承Thread类。

代码语言:java
复制
public class MyThread extends Thread {  
    @Override  
    public void run() {  
        System.out.println("MyThread is running.");  
    }  
  
    public static void main(String[] args) {  
        MyThread thread = new MyThread();  
        thread.start(); // 启动线程  
    }  
}

2. 实现Runnable接口

通过实现Runnable接口并重写其run()方法,也可以创建线程。这种方式更加灵活,因为Java类可以实现多个接口。但是,与继承Thread类一样,这种方式也无法直接获取线程的运算结果。

代码语言:java
复制
public class MyRunnable implements Runnable {  
    @Override  
    public void run() {  
        System.out.println("MyRunnable is running.");  
    }  
  
    public static void main(String[] args) {  
        Thread thread = new Thread(new MyRunnable());  
        thread.start(); // 启动线程  
    }  
}

3. 实现Callable接口 + FutureTask

Callable接口与Runnable接口类似,但Callable可以返回执行结果,并且可以声明抛出异常。FutureTask类实现了Future和Runnable接口,它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。这种方式虽然可以获取线程的运算结果并处理异常,但不利于控制服务器中的线程资源,可能导致服务器资源耗尽。

代码语言:java
复制
import java.util.concurrent.*;  
  
public class MyCallable implements Callable<String> {  
    @Override  
    public String call() throws Exception {  
        return "MyCallable result";  
    }  
  
    public static void main(String[] args) throws ExecutionException, InterruptedException {  
        ExecutorService executor = Executors.newSingleThreadExecutor();  
        FutureTask<String> futureTask = new FutureTask<>(new MyCallable());  
        executor.submit(futureTask);  
          
        // 主线程等待子线程执行完毕并获取结果  
        String result = futureTask.get();  
        System.out.println(result); // 输出 "MyCallable result"  
          
        executor.shutdown(); // 关闭线程池  
    }  
}

4. 使用线程池

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的ThreadFactory创建一个新线程。通过线程池,我们可以更好地控制和管理线程资源,提高系统性能和稳定性。

代码语言:java
复制
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
  
public class ThreadPoolExample {  
    public static void main(String[] args) {  
        ExecutorService executor = Executors.newFixedThreadPool(3); // 创建一个固定大小的线程池  
  
        for (int i = 0; i < 5; i++) {  
            final int taskId = i;  
            executor.submit(() -> {  
                System.out.println("Task " + taskId + " is running by " + Thread.currentThread().getName());  
            });  
        }  
  
        executor.shutdown(); // 关闭线程池  
    }  
}

二、线程池的七大参数

在Java中,线程池的核心是ThreadPoolExecutor类,它提供了七个参数来配置线程池的行为:

  1. corePoolSize:核心线程数,即线程池中的常驻线程数。即使这些线程在空闲时也不会被销毁。
  2. maximumPoolSize:线程池允许的最大线程数。当队列满了且已创建的线程数小于maximumPoolSize,则线程池会再创建新的线程执行任务。
  3. keepAliveTime:当线程数大于核心线程数时,这是多余的空闲线程在终止前等待新任务的最长时间。
  4. unit:keepAliveTime参数的时间单位,通常是TimeUnit.MILLISECONDS。
  5. workQueue:用于保存等待执行的任务的阻塞队列。
  6. threadFactory:用于创建新线程的线程工厂,可以通过自定义的ThreadFactory来创建具有特定名称、优先级、是否为守护线程等的线程。
  7. handler:当线程池无法处理新任务时使用的饱和策略。
代码语言:java
复制
import java.util.concurrent.*;  
  
public class ThreadPoolExecutorExample {  
    public static void main(String[] args) {  
        int corePoolSize = 2; // 核心线程数  
        int maximumPoolSize = 5; // 最大线程数  
        long keepAliveTime = 60L; // 空闲线程的存活时间  
        TimeUnit unit = TimeUnit.SECONDS; // 时间单位  
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(10); // 任务队列  
        ThreadFactory threadFactory = Executors.defaultThreadFactory(); // 线程工厂  
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); // 拒绝策略  
  
        ThreadPoolExecutor executor = new ThreadPoolExecutor(  
                corePoolSize,  
                maximumPoolSize,  
                keepAliveTime,  
                unit,  
                workQueue,  
                threadFactory,  
                handler  
        );  
  
        // 提交任务到线程池  
        executor.execute(() -> System.out.println("Task executed by thread pool."));  
  
        executor.shutdown(); // 关闭线程池  
    }  
}

三、常见的线程池类型

Java的java.util.concurrent包提供了几种常见的线程池实现:

FixedThreadPool:固定大小的线程池,它的核心线程数和最大线程数都是指定的,并且工作队列没有大小限制。

代码语言:txt
复制
ExecutorService executor = Executors.newFixedThreadPool(5); // 创建固定大小的线程池

CachedThreadPool:可缓存的线程池,它的核心线程数为0,最大线程数为Integer.MAX_VALUE,工作队列是SynchronousQueue。这种线程池适合执行大量的耗时较少的任务。

代码语言:txt
复制
ExecutorService executor = Executors.newCachedThreadPool(); // 创建可缓存的线程池

ScheduledThreadPool:定长线程池,支持定时及周期性任务执行。

代码语言:txt
复制
ExecutorService executor = Executors.newCachedThreadPool(); // 创建可缓存的线程池

SingleThreadExecutor:单线程化的Executor,它使用单一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

代码语言:txt
复制
ExecutorService executor = Executors.newSingleThreadExecutor(); // 创建单线程化的Executor

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、线程初始化方式
    • 1. 继承Thread类
      • 2. 实现Runnable接口
        • 3. 实现Callable接口 + FutureTask
          • 4. 使用线程池
          • 二、线程池的七大参数
          • 三、常见的线程池类型
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档