Java 并发(Future 模式)

>Future 提前完成任务

首先,梳理一下,多线程为我们带来什么:

  • 充分利用CPU
  • 当我们需要并行处理一件任务(并不一定是为了提高运算速度,而且很多时候性能并不是绝对的问题,同一时间需要处理多个任务,就要开线程)

Future,未来,什么是未来?

设想一种情景,线程等待生产产品的时候,想做点其他的事情

产品:

public class Product {
	private int id;
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Product [id=" + id + ", name=" + name + "]";
	}

	public Product() {

	}

	public Product(int id, String name) {
		this.id = id;
		this.name = name;
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					// 模拟产品生产过程
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}).start();
		
	}
}

生产工厂:

public class ProductFactory {
	public Product buildProduct() {
		return new Product();
	}
}

测试线程:

public class Go {

	public static void main(String[] args) {
		ProductFactory pf=new ProductFactory();
		System.out.println("准备生产产品");
		Product product = pf.buildProduct();
		System.out.println("生产产品的时候,我想干点别的...");
		System.out.println("产品生产完毕"+product);
	}
}

结果:

准备生产产品
生产产品的时候,我想干点别的...
产品生产完毕Product [id=1, name=tea]

上面的代码的问题?

首先,为了模拟产品构建比较慢,我们使用Thread.sleep(),然后我们将Thread.sleep() 又放到了一个线程中,这是一种错误的代码,真正模拟生产产品,也就是初始化赋值的代码并没有办法拿到线程里面;

如果不能开线程,那么在真正产品生产结束之前,线程真就不能干点别的。

另外,在构造函数中不能开线程,会造成This 逃逸现象(在对象构造完成之前,就发布了引用)。

再来,新问题:

如果现在要去蛋糕店定做一个蛋糕,蛋糕制作期间,想先处理下其他事情,先拿到订单,做好之后再拿到实际的蛋糕

建立模型:

为什么要设计成这个样子,首先找老板要定做一个蛋糕,需要一个返回值,老板一开始只能给我一个订单,蛋糕和订单 并不是同一个类型,所以要同时继承一个接口/共同继承一个类,这样满足类之间的多态。

其中订单中对蛋糕存在一种包装,存在依赖关系,真正干活的还得是Real。

之前你拿蛋糕是直接在那等着做好了,直接拿蛋糕,现在有了这层 “订单包装”之后,既方便“老板”先给你一个订单,然后开线程把一个未完成的“订单”完成,同时你去做其他事情,也可以通过“订单”这个包装来控制:

  • 蛋糕未做完之前,来取就得等待,等做好了就通知你取“蛋糕”。
  • 蛋糕做好之后来取,直接就可以获得蛋糕。
/**
 * 数据访问接口
 */
public interface Data {
	public String obtainString();
}
/**
 * 类似于产品 实际数据 "蛋糕"
 */
public class Real implements Data {
	public Real() {
		try {
			//模拟产品生产过程
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public String obtainString() {
		//一旦可以调用返回,即代表产品生产完成
		return "hello world";
	}
}
/**
 * 可以理解为 "订单"
 */
public class Future implements Data {
	private Real real;
	private boolean ready = false;

	public synchronized void setReal(Real real) {
		if (ready) {
			return;
		}
		this.real = real;
		this.ready = true;
		notifyAll();
	}

	@Override
	public synchronized String obtainString() {
		if (!ready) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return real.obtainString();
	}
}
/**
 * 返回Data对象  可以理解为 "蛋糕店"
 */
public class RequestHandler {
	public Data requestData() {
		final Future future = new Future();
		//开了一个线程去 做"蛋糕",可以想象这个线程需要运行一段时间
		new Thread(new Runnable() {
			@Override
			public void run() {
				Real real = new Real();
				future.setReal(real);
			}
		}).start();
		//先给你一个订单
		return future;
	}
}
public class Go {

	public static void main(String[] args) throws InterruptedException {
		RequestHandler handler = new RequestHandler();
		//这里向"老板"handler 请求做蛋糕 ,拿到订单
		Data data1 = handler.requestData();
		Data data2 = handler.requestData();
		
		/**
		 * 这里我们可以做其他事情,而不是等待
		 */
		System.out.println("我在做其他事情...");
		// Thread.sleep(3000);
		System.out.println(data1.obtainString());
		System.out.println(data2.obtainString());
	}
}

 

 

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