提交线程方式

Java 提交线程的几种方式

在 Java 中,提交线程任务有多种方式,以下是主要的几种方法及其适用场景:

1. 直接创建 Thread 对象

java

复制

下载

// 方式1:继承Thread类
class MyThread extends Thread {@Overridepublic void run() {System.out.println("Thread running");}
}// 方式2:实现Runnable接口
Thread thread = new Thread(() -> {System.out.println("Runnable running");
});// 启动线程
new MyThread().start();
thread.start();

特点

  • 最基础的线程创建方式

  • 适合简单的单线程任务

  • 缺乏线程复用能力

2. 使用 ExecutorService 线程池

java

复制

下载

// 创建线程池
ExecutorService executor = Executors.newFixedThreadPool(5);// 提交任务方式1:execute() - 无返回值
executor.execute(() -> {System.out.println("Task executed");
});// 提交任务方式2:submit() - 可返回Future对象
Future<String> future = executor.submit(() -> {Thread.sleep(1000);return "Task result";
});// 获取结果
try {String result = future.get(); // 阻塞获取System.out.println(result);
} catch (InterruptedException | ExecutionException e) {e.printStackTrace();
}// 关闭线程池
executor.shutdown();

特点

  • 推荐的生产环境使用方式

  • 提供线程复用,减少创建线程开销

  • 支持任务返回值(Future)

  • 可控制并发线程数量

3. 使用 CompletableFuture (Java 8+)

java

复制

下载

// 异步执行
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {System.out.println("Run async task");
});// 异步执行并返回结果
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {return "Async result";
});// 结果处理
future2.thenAccept(result -> {System.out.println("Got result: " + result);
});// 组合多个Future
CompletableFuture<String> combined = future2.thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " and more")
);// 等待所有完成
CompletableFuture.allOf(future1, future2).join();

特点

  • 强大的异步编程能力

  • 支持链式调用和组合操作

  • 内置异常处理机制

  • 默认使用ForkJoinPool.commonPool()

4. 使用 ForkJoinPool (适合分治任务)

java

复制

下载

class MyRecursiveTask extends RecursiveTask<Integer> {private final int threshold = 10;private final int[] array;private final int start;private final int end;// 构造函数...@Overrideprotected Integer compute() {if (end - start <= threshold) {// 直接计算return Arrays.stream(array, start, end).sum();} else {// 拆分任务int mid = (start + end) / 2;MyRecursiveTask left = new MyRecursiveTask(array, start, mid);MyRecursiveTask right = new MyRecursiveTask(array, mid, end);left.fork();right.fork();return left.join() + right.join();}}
}// 使用
int[] data = new int[100];
Arrays.fill(data, 1);
ForkJoinPool pool = new ForkJoinPool();
int result = pool.invoke(new MyRecursiveTask(data, 0, data.length));
System.out.println("Sum: " + result);

特点

  • 专为分治算法设计

  • 工作窃取(work-stealing)机制提高效率

  • 适合CPU密集型任务

5. 使用 Spring 的 @Async 注解

java

复制

下载

@Service
public class AsyncService {@Async  // 使用自定义线程池可在括号内指定public CompletableFuture<String> asyncMethod() {// 模拟耗时操作Thread.sleep(1000);return CompletableFuture.completedFuture("Async result");}
}// 配置类
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(100);executor.setThreadNamePrefix("Async-");executor.initialize();return executor;}
}

特点

  • Spring框架提供的异步支持

  • 方法级别声明式异步调用

  • 可与Spring其他功能集成

最佳实践建议

  1. 生产环境优先使用线程池,避免直接创建线程

  2. 根据任务类型选择合适线程池

    • CPU密集型:固定大小线程池(核数+1)

    • IO密集型:可扩展线程池

  3. 合理设置线程池参数

    java

    复制

    下载

    new ThreadPoolExecutor(corePoolSize,  // 常驻线程数maximumPoolSize,  // 最大线程数keepAliveTime,  // 空闲线程存活时间TimeUnit.MILLISECONDS,  // 时间单位new LinkedBlockingQueue<>(capacity),  // 工作队列threadFactory,  // 线程工厂handler  // 拒绝策略
    );
  4. 使用Future或CompletableFuture获取结果,避免线程阻塞

  5. 记得关闭线程池,避免资源泄漏

选择哪种方式取决于具体需求,简单任务可以直接使用Thread,复杂异步编程推荐CompletableFuture,Web应用可以使用@Async注解。

6.submit

Java 中 submit() 方法详解

submit() 是 ExecutorService 接口提供的一个核心方法,用于向线程池提交任务并返回 Future 对象。相比 execute() 方法,submit() 提供了更强大的功能和控制能力。

1. submit() 方法的基本形式

ExecutorService 提供了三种 submit() 重载方法:

java

复制

下载

// 提交Runnable任务,返回Future<?>
Future<?> submit(Runnable task);// 提交Runnable任务并指定返回结果,返回Future<T>
<T> Future<T> submit(Runnable task, T result);// 提交Callable任务,返回Future<T>
<T> Future<T> submit(Callable<T> task);

2. 基本使用示例

示例1:提交Runnable任务

java

复制

下载

ExecutorService executor = Executors.newFixedThreadPool(2);// 提交Runnable任务
Future<?> future = executor.submit(() -> {System.out.println("Runnable task running");Thread.sleep(1000);
});// 检查任务是否完成
if (future.isDone()) {System.out.println("Task completed");
}executor.shutdown();

示例2:提交Callable任务并获取结果

java

复制

下载

ExecutorService executor = Executors.newFixedThreadPool(2);// 提交Callable任务
Future<String> future = executor.submit(() -> {Thread.sleep(1000);return "Task result";
});try {// 获取任务结果(阻塞直到任务完成)String result = future.get();System.out.println("Result: " + result);
} catch (InterruptedException | ExecutionException e) {e.printStackTrace();
}executor.shutdown();

示例3:提交Runnable并预置返回结果

java

复制

下载

ExecutorService executor = Executors.newSingleThreadExecutor();// 预置返回结果
String presetResult = "Preset value";// 提交Runnable并指定返回结果
Future<String> future = executor.submit(() -> {System.out.println("Task running");// 这里不返回任何值
}, presetResult);try {// 获取的将是预设的结果String result = future.get();System.out.println("Result: " + result);  // 输出: Preset value
} catch (InterruptedException | ExecutionException e) {e.printStackTrace();
}executor.shutdown();

3. submit() 与 execute() 的区别

特性submit()execute()
返回值返回Future对象无返回值
异常处理异常封装在Future中直接抛出异常
任务类型支持Runnable和Callable仅支持Runnable
结果获取可通过Future.get()获取无法获取结果
任务取消支持通过Future.cancel()取消不支持取消

4. submit() 的高级用法

批量提交任务

java

复制

下载

ExecutorService executor = Executors.newFixedThreadPool(4);
List<Callable<String>> tasks = Arrays.asList(() -> { Thread.sleep(1000); return "Task1"; },() -> { Thread.sleep(1500); return "Task2"; },() -> { Thread.sleep(500); return "Task3"; }
);// 批量提交任务
List<Future<String>> futures = executor.invokeAll(tasks);// 获取所有结果
for (Future<String> future : futures) {System.out.println(future.get());
}executor.shutdown();

超时控制

java

复制

下载

Future<String> future = executor.submit(() -> {Thread.sleep(2000);return "Result";
});try {// 设置超时时间为1秒String result = future.get(1, TimeUnit.SECONDS);
} catch (TimeoutException e) {System.out.println("Task timed out");future.cancel(true);  // 取消任务
}

异常处理

java

复制

下载

Future<String> future = executor.submit(() -> {if (someCondition) {throw new RuntimeException("Something went wrong");}return "Success";
});try {String result = future.get();
} catch (ExecutionException e) {// 获取任务中抛出的实际异常Throwable cause = e.getCause();System.out.println("Task failed: " + cause.getMessage());
}

5. 最佳实践

  1. 总是检查Future.get()的异常:任务中的异常会被包装在ExecutionException中

  2. 合理设置超时:避免长时间阻塞,特别是UI线程

  3. 考虑使用CompletionService:当需要按完成顺序处理结果时

    java

    复制

    下载

    ExecutorService executor = Executors.newFixedThreadPool(4);
    CompletionService<String> completionService = new ExecutorCompletionService<>(executor);// 提交任务
    completionService.submit(() -> "Task1");
    completionService.submit(() -> "Task2");// 按完成顺序获取结果
    for (int i = 0; i < 2; i++) {Future<String> completedFuture = completionService.take();System.out.println(completedFuture.get());
    }
  4. 记得关闭线程池:使用完ExecutorService后调用shutdown()

submit() 方法是Java并发编程中非常强大的工具,它提供了对异步任务执行状态和结果的控制能力,是构建复杂异步系统的基石。