Java线程返回值

这篇博客探讨了Runnable接口的局限性,如无法返回值和抛出checkedException,然后介绍了Callable接口的优势,它允许有返回值并能声明异常。通过FutureTask和Future类,可以实现对任务执行状态的监控、取消任务以及获取执行结果。示例代码展示了如何创建Callable任务并使用Future获取结果。

Runnable 的缺陷:

不能返回一个返回值

不能抛出 checked Exception (类或接口方法中Throws xxException为方法执行过程中抛出的异常向上一级调用反馈[调用者须try明确异常发生的代码位置或继续上一级反馈])

 Callable的call方法可以有返回值,可以声明抛出异常。和 Callable 配合的有一个 Future 类, 通过 Future 可以了解任务执行情况,或者取消任务的执行,还可获取任务执行的结果,这些 功能都是 Runnable 做不到的,Callable 的功能要比 Runnable 强大。 

Future 的主要功能 Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。 必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。

简单的代码调试实例:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Demo {
	
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		Demo demo = new Demo();
		Task tcall = demo.new Task();
		FutureTask<User> task = new FutureTask<User>(tcall);
		demo.new Tthead(task).start();
		System.out.println(task.get().getUname());
	}
	
	/**
	 * @Desc: Task-线程Callable实现类
	 * @author hx
	 * @date 2021年12月30日
	 */
	 class Task implements Callable<User> {
		@Override
		public User call() throws Exception {
			System.out.println("运行Callable线程,返回Model结果");
			User user = new User();
			user.setUname("learnworm");
			user.setAge(32);
			return user;
		}
	}
	
	 /**
	  * @Desc: User(用户业务对象)
	  * @author hx
	  * @date 2021年12月30日
	  */
	 class User {
		private String uname ;
		private Integer age;
		public String getUname() {
			return uname;
		}
		public void setUname(String uname) {
			this.uname = uname;
		}
		public Integer getAge() {
			return age;
		}
		public void setAge(Integer age) {
			this.age = age;
		}
	}
	
	/**
	 * @Desc: 用户定义的Thread线程
	 * @author hx
	 * @date 2021年12月30日
	 */
	class Tthead extends Thread{

		public Tthead(Runnable target) {
			super(target);
			// TODO Auto-generated constructor stub
		}
			
	}
}

Java线程返回值的实现方式主要有以下几种: ### 实现Callable接口 实现`Callable`接口的类可以返回一个结果。`Callable`接口是一个泛型接口,其中的`call()`方法需要返回指定泛型类型的值。可以通过`FutureTask`来包装`Callable`对象,并使用线程来执行`FutureTask`。调用`FutureTask`的`get()`方法可以获取线程执行的结果。示例代码如下: ```java import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; class TestA implements Callable<Integer> { @Override public Integer call() throws Exception { Thread.sleep(1000); return sum(); } private int sum() { int sum = 0; for (int i = 0; i <= 100; i++) { sum += i; } return sum; } } public class TestFutureTask { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<Integer> futureTask = new FutureTask<>(new TestA()); Thread thread = new Thread(futureTask); thread.start(); Integer integer = futureTask.get(); System.out.println(integer); } } ``` 上述代码中,`TestA`类实现了`Callable<Integer>`接口,在`call()`方法中进行求和操作并返回结果。在`main`方法中,使用`FutureTask`包装`TestA`对象,启动线程执行`FutureTask`,最后通过`get()`方法获取结果[^4]。 ### 利用线程池 可以利用线程池带有返回值的方式批量处理大量数据。创建`ThreadPoolExecutor`线程池,使用`CountDownLatch`同步工具类让主线程一直等待,直到子线程执行完后再执行。处理完成后将所有的返回内容进行组装拼接。代码示例可参考如下逻辑实现: ```java import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; public class ThreadPoolExample { public static void main(String[] args) throws InterruptedException, ExecutionException { // 创建线程池 ThreadPoolExecutor executor = new ThreadPoolExecutor( 5, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>() ); // 任务列表 List<Future<String>> futures = new ArrayList<>(); // 模拟多个任务 for (int i = 0; i < 5; i++) { Callable<String> task = new MyCallable(i); futures.add(executor.submit(task)); } // 收集结果 StringBuilder result = new StringBuilder(); for (Future<String> future : futures) { result.append(future.get()); } // 关闭线程池 executor.shutdown(); System.out.println(result.toString()); } static class MyCallable implements Callable<String> { private final int id; public MyCallable(int id) { this.id = id; } @Override public String call() throws Exception { return "Result from task " + id + "\n"; } } } ``` 在上述代码中,创建了一个线程池,提交多个`Callable`任务到线程池执行,使用`Future`对象来获取每个任务的结果,最后将结果进行拼接。使用`CountDownLatch`可参考如下示例来控制主线程等待子线程完成: ```java import java.util.concurrent.*; public class CountDownLatchExample { public static void main(String[] args) throws InterruptedException { int taskCount = 5; CountDownLatch latch = new CountDownLatch(taskCount); ThreadPoolExecutor executor = new ThreadPoolExecutor( 5, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>() ); for (int i = 0; i < taskCount; i++) { executor.submit(() -> { try { // 模拟任务执行 Thread.sleep(1000); System.out.println("Task completed"); } catch (InterruptedException e) { e.printStackTrace(); } finally { latch.countDown(); } }); } // 主线程等待 latch.await(); System.out.println("All tasks are completed"); executor.shutdown(); } } ``` 这里创建了`CountDownLatch`,每个子线程执行完后调用`countDown()`方法,主线程调用`await()`方法等待所有子线程完成[^1]。 ### 自定义类继承Thread类 虽然`Thread`类的`run()`方法没有返回值,但可以通过自定义类继承`Thread`类,在类中定义一个成员变量来存储线程执行的结果。示例代码如下: ```java class MyThread extends Thread { private int result; @Override public void run() { result = sum(); } private int sum() { int sum = 0; for (int i = 0; i <= 100; i++) { sum += i; } return sum; } public int getResult() { return result; } } public class ThreadExample { public static void main(String[] args) throws InterruptedException { MyThread thread = new MyThread(); thread.start(); thread.join(); int result = thread.getResult(); System.out.println(result); } } ``` 在上述代码中,`MyThread`类继承自`Thread`类,在`run()`方法中计算求和结果并存储在`result`成员变量中,通过`getResult()`方法获取结果。使用`join()`方法确保主线程等待子线程执行完毕后再获取结果[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值