java.util.concurrent.locks.LockSupport 类,故名思义,是一个线程辅助类,它的一个重要功能就是实现线程间的通信,阻塞唤醒等,它与Object 的 wait方法和notify方法相比,有很多优势,目前我就发现俩:
1、不需要显示地加锁,不需要很多的try--catch,代码更加简洁
2、使用LockSupport唤醒线程不需要关心阻塞和唤醒的先后顺序
Future设计模式是一种提高性能的编程模式,java.util.concurrent.FutureTask.FutureTask 类就是实现这种方式的封装类,我们可以很快速地使用FutureTask 来进行编程,它的主要思想是:如果有一个很耗时的操作,就开一个新线程去做它,主线程继续执行后续的操作,等主线程执行完后,再调用方法去获取那个线程的执行结果,如果那个线程还没执行完,主线程阻塞等待。这是一种并行的方式,可以在程序中使用以提高系统响应时间。
示例一:使用FutureTask 的一个简单例子:
package com.jack.jucstudy;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class UseFuture implements Callable<String>{
private String query;
private long queryTime;
public UseFuture(String query, long querytime) {
super();
this.query = query;
this.queryTime = querytime;
}
@Override
public String call() throws Exception {
Thread.sleep(7000);
return this.query + "执行完成";
}
public static void main(String[] args) throws Exception {
FutureTask<String> futureTask1 = new FutureTask<String>(new UseFuture("query1",5000));
FutureTask<String> futureTask2 = new FutureTask<String>(new UseFuture("query2",10000));
ExecutorService threadPool = Executors.newFixedThreadPool(2);
threadPool.submit(futureTask1);//异步的操作
threadPool.submit(futureTask2);
threadPool.shutdown();
Thread.sleep(2000); //两秒钟之后获取任务执行结果
System.out.println("2秒之后阻塞获取任务结果。");
String res1 = futureTask1.get();//此处阻塞,等待执行结果
System.out.println("----------------");
String res2 = futureTask2.get();
System.out.println(res1);
System.out.println(res2);
}
}
注意点:1、自己定义的任务需要实现Callable接口,实现Runnable接口也行,但是使用Callable可以有明确的返回值,并且可以抛出异常;2、FutureTask需要使用线程池提交,而不能使用start()方法启动任务,使用完线程池记得关闭。
下面使用LockSupport简单实现一下Future设计模式:
FutureData类,相当于上面例子中的FutureTask 角色,它只是一个空壳,它里面的真实数据是由另一个线程完成设置的。
package com.jack.jucstudy.future;
import java.util.concurrent.locks.LockSupport;
public class FutureData {
Thread main;
private boolean isReady;
private RealData real;
public void setRealData(RealData real) {
//到这个方法说明数据已经准备好了
this.real = real;
isReady = true;
LockSupport.unpark(main);
}
/**
* 获取真实数据的方法
* 由于使用LockSupport的unpark方法时,需要传入一个线程,即被阻塞的线程
* @param t
* @return
*/
public String get(Thread t) {
main = t;
while(!isReady) {
LockSupport.park();
}
return real.getRequest();
}
public void getData(String questStr) {
new Thread(new Runnable() {
@Override
public void run() {
//new一个RealData的操作是模拟查询数据的过程
RealData real = new RealData(questStr);
setRealData(real);
}
}).start();;
}
}
package com.jack.jucstudy.future;
/**
* 定义一个FutureClient类,用于生成FutureData,而FutureData
* 相当于上面例子中的 FutureTask 角色。
*/
public class FutureClient {
//这个方法很重要,它在返回一个空壳对象的同时,还要起一个线程去获取数据
//然后把获取到的数据设置到这个空壳里面去。
public FutureData getRequest(String questStr) {
FutureData future = new FutureData();
future.getData(questStr);
return future;
}
//测试
public static void main(String[] args) {
FutureClient futureClient = new FutureClient();
FutureData data = futureClient.getRequest("查询参数...");
//主线程可以去做自己的事了。。。
try {
System.out.println("主线程开始做自己的事了");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String result = data.get(Thread.currentThread());
System.out.println("result = " + result);
}
}