继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Java 通过回调获取线程返回数据

程序员大阳
关注TA
已关注
手记 357
粉丝 1.5万
获赞 1523

1. 低调自然的回调理念

多线程嘛,就是老板同时安排多个人去完成工作,老板当然希望能知道每个工作的完成情况。

最简单的想法,可以轮询,就是老板每隔一段时间,就去问下每个人工作完成了没。这个方法可行吗,当然可行,但是非常浪费老板的时间啊,老板铁定不开心。

那么怎么做比较好呢,当然是每个人完成了自己的工作后进行汇报,将工作结果汇报给老板。

这种线程执行完成后主动告知主程序结果的方式,被称之为回调(Callback)。

不要被Callback这种看似高端大气的名词唬住,其实回调是非常低调、自然、常见的思维理念。

2. 回调静态方法

由于静态方法是全局通用的,所以我们可以非常容易的在线程中回调主程序中的静态方法。

先看线程,执行结束后回调主程序的静态方法来告诉主程序执行结果。

/**
 * 员工:负责读取文件大小
 */
public class ReadFileMan implements Runnable {
	/**
	 * 文件名
	 */
	private String fileName;

	public ReadFileMan(String fileName) {
		this.fileName = fileName;
	}

	@Override
	public void run() {
		File f = new File(fileName);
		if (f.exists() && f.isFile()) {
			// 回调主程序的静态方法
			ReadFileBoss.knowFileLength(fileName, f.length());
		} else {
			// 回调主程序的静态方法
			ReadFileBoss.knowFileLength(fileName, f.length());
		}
	}
}

主程序比较简单,启动线程,然后等待回调即可:

/**
 * 主程序
 */
public class ReadFileBoss {
	public static void knowFileLength(String fileName, long length) {
		System.out.println("老板知道了文件[" + fileName + "]大小:" + length);
	}

	public static void main(String[] args) {
		// 启动线程
		ReadFileMan readFileMan = new ReadFileMan("D:\\temp\\1.txt");
		Thread thread = new Thread(readFileMan);
		thread.start();
		// 输出:老板知道了文件[D:\temp\1.txt]大小:6
	}
}

在上面的程序中,老板ReadFileBoss告诉员工readFileMan去读取文件大小后,只需要等待员工上报结果即可。

对员工来说,执行完毕后直接回调老板的静态方法,很容易。

3. 回调实例方法

还有一种方法是回调实例方法,这种模式相当于每个员工有一个经理,负责管理员工的日常行为并监督执行结果,老板只要管理经理即可,员工只需要向经理汇报。

OK,员工线程需要知道自己的经理是谁,所以修改如下:

/**
 * 员工:负责读取文件大小
 */
public class ReadFileMan implements Runnable {
	/**
	 * 文件名
	 */
	private String fileName;

	/**
	 * 员工需要知道自己的经理是谁
	 */
	private ReadFileManager readFileManager;

	public ReadFileMan(String fileName, ReadFileManager readFileManager) {
		this.fileName = fileName;
		this.readFileManager = readFileManager;
	}

	@Override
	public void run() {
		File f = new File(fileName);
		if (f.exists() && f.isFile()) {
			// 回调经理的实例方法
			readFileManager.knowFileLength(fileName, f.length());
		} else {
			// 回调经理的静态方法
			readFileManager.knowFileLength(fileName, f.length());
		}
	}
}

经理需要安排员工去工作,然后经理还需要管理工作结果。

/**
 * 经理
 */
public class ReadFileManager {
	/**
	 * 执行结果
	 */
	public void knowFileLength(String fileName, long length) {
		System.out.println("经理知道了文件[" + fileName + "]大小:" + length);
		System.out.println("经理根据工作情况进行进一步处理");
	}

	/**
	 * 安排工作
	 */
	public void plan() {
		// 启动线程
		ReadFileMan readFileMan = new ReadFileMan("D:\\temp\\1.txt", this);
		Thread thread = new Thread(readFileMan);
		thread.start();
	}
}

老板就轻松了,直接让经理去负责:

/**
 * 主程序
 */
public class ReadFileBoss {
	public static void main(String[] args) {
		// 把事情交给经理就行了
		ReadFileManager manager=new ReadFileManager();
		manager.plan();
		// 执行结果:经理知道了文件[D:\temp\1.txt]大小:6
	}	
}

4. 小结

从上面的实例中能发现,让经理去管理时更好的,因为每个经理可以管理多个员工(多个员工线程回调一个经理实例即可);每个员工也可以汇报给多个经理(员工保存回调经理的列表);这样非常灵活。

让一个实例去管理线程,可以实现各种管理逻辑,便于拓展,也更加符合面向对象编程的思想。

所以建议采用通过实例方法回调获取线程数据。

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP