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其他功能集成
最佳实践建议
-
生产环境优先使用线程池,避免直接创建线程
-
根据任务类型选择合适线程池:
-
CPU密集型:固定大小线程池(核数+1)
-
IO密集型:可扩展线程池
-
-
合理设置线程池参数:
java
复制
下载
new ThreadPoolExecutor(corePoolSize, // 常驻线程数maximumPoolSize, // 最大线程数keepAliveTime, // 空闲线程存活时间TimeUnit.MILLISECONDS, // 时间单位new LinkedBlockingQueue<>(capacity), // 工作队列threadFactory, // 线程工厂handler // 拒绝策略 );
-
使用Future或CompletableFuture获取结果,避免线程阻塞
-
记得关闭线程池,避免资源泄漏
选择哪种方式取决于具体需求,简单任务可以直接使用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. 最佳实践
-
总是检查Future.get()的异常:任务中的异常会被包装在ExecutionException中
-
合理设置超时:避免长时间阻塞,特别是UI线程
-
考虑使用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()); } -
记得关闭线程池:使用完ExecutorService后调用shutdown()
submit() 方法是Java并发编程中非常强大的工具,它提供了对异步任务执行状态和结果的控制能力,是构建复杂异步系统的基石。