手寫模擬Callable接口有返回值的Future模式,notify和wait的使用

總所周(java程序員)知,Runnable接口是沒有返回值的,但是他的兄弟Callable有返回值。

貼代碼吧。

 

/**
 * 模擬Callable接口的future模式
 */
public class FutureModel {

	public static void main(String[] args) throws InterruptedException {
		System.out.println(Thread.currentThread().getName() + ":start...");// 主線程開始
		// 創建工作對象,相當於Callable變量
		Task<String> task = new Task<String>() {
			@Override
			public String run() {
				// 這裏可以放置任何代碼,比如網絡請求,返回響應結果
				System.out.println(Thread.currentThread().getName() + ":start...");// 子線程開始
				try {
					System.out.println(Thread.currentThread().getName() + ":work...");// 子線程工作

					Thread.sleep(2000);// 模擬阻塞
					int a = 1 / 0;
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + ":done...");// 子線程結束
				return "張5G";
			}
		};
		// FuturePool相當於線程池,這裏是提交任務返回Future對象
		FutureData<String> futureData = FuturePool.submit(task);// 這裏不會形成阻塞,主線程繼續運行

		System.out.println(Thread.currentThread().getName() + ":work...");// 主線程工作

		String result = futureData.get();// 這裏會阻塞調用線程,如主線程阻塞
		System.out.println(Thread.currentThread().getName() + ":result:" + result);// 主線程獲取到結果

		System.out.println(Thread.currentThread().getName() + ":done...");// 主線程結束
	}

}

/**
 * 相當於Callable接口
 */
interface Task<T> {
	T run();
}

/**
 * 真正執行Task中的run方法
 */
class TaskData<T> {
	Task<T> task;
	T data;
	volatile boolean isDone = false;

	public TaskData(Task<T> task) {
		this.task = task;
	}

	protected synchronized void doWork() {
		try {
			data = task.run();
		} finally {
			isDone = true;
			notify();// 喚醒等待的線程
		}

	}

	public synchronized T getFuture() throws InterruptedException {
		while (!isDone) {
			wait();// 如果沒有執行完一直等待
		}
		return data;
	}

}

/**
 * 模擬線程池接收任務,委派線程去執行,所以不會阻塞調用線程
 */
class FuturePool {
	public static <T> FutureData<T> submit(Task<T> task) {
		FutureData<T> futureData = new FutureData<T>(task);
		new Thread(new Runnable() {
			@Override
			public void run() {
				futureData.taskData.doWork();
			}
		}).start();
		return futureData;
	}
}

class FutureData<T> {
	TaskData<T> taskData;

	public FutureData(Task<T> task) {
		taskData = new TaskData<T>(task);
	}

	public T get() throws InterruptedException {
		return taskData.getFuture();
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章