文档章节

走近Guava(四): 并发

ihaolin
 ihaolin
发布于 2014/04/05 12:53
字数 930
阅读 9696
收藏 19

并发:

  • Guava集合处理是很强大的(这些在jdk8中都有些引入),但Guava发光的地方是并发

Monitor

  • Monitor实现同步
/**
 * 通过Monitor的Guard进行条件阻塞
 */
public class MonitorSample {
	private List<String> list = new ArrayList<String>();
	private static final int MAX_SIZE = 10;
	private Monitor monitor = new Monitor();
	
	private Monitor.Guard listBelowCapacity = new Monitor.Guard(monitor) {
		@Override
		public boolean isSatisfied() {
			return list.size() < MAX_SIZE;
		}
	};

	public void addToList(String item) throws InterruptedException {
		monitor.enterWhen(listBelowCapacity); //Guard(形如Condition),不满足则阻塞,而且我们并没有在Guard进行任何通知操作
		try {
			list.add(item);
		} finally {
			monitor.leave();
		}
	}
}
  • Monitor就像java本土的synchronized, ReentrantLock一样,每次只运行一个线程占用,且可重占用,每一次占用会对应一次退出占用。

Monitor最佳实践:

  • 就如上面,我们通过if条件来判断是否可进入Monitor代码块,并再try/finally中释放:
if (monitor.enterIf(guardCondition)) {
        try {
              doWork();
    } finally {
           monitor.leave();
       }
}

其他的Monitor访问方法:

Monitor.enter //进入Monitor块,将阻塞其他线程知道Monitor.leave
Monitor.tryEnter //尝试进入Monitor块,true表示可以进入, false表示不能,并且不会一直阻塞
Monitor.tryEnterIf //根据条件尝试进入Monitor块

这些方法都有对应的限时版本。

ListenableFuture类

  • jdk5之后有了Future这种异步执行的结构
ExecutorService executor = Executors.newCachedThreadPool();
   Future<Integer> future = executor.submit(new Callable<Integer>(){
                                public Integer call() throws Exception{
                                   return service.getCount();
} });
//Retrieve the value of computation
Integer count = future.get();
  • ListenableFuture对Future进行了扩展,允许注册一个回调函数,task执行完后自动调用。
  • 获取ListableFuture对象。

正如我们获取Future对象要通过ExecutorService.submit(Callable)来获取一样,我们可以这样创建ListenableFuture对象:

executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUM_THREADS)); //包装Executors创建的线程池
ListenableFuture<String> listenableFuture = executorService.submit(new Callable<String>()...); //获取ListableFuture对象
listenableFuture.addListener(new Runnable() {
      @Override
      public void run() {
          methodToRunOnFutureTaskCompletion();
      }
}, executorService); //注册回调函数

FutureCallback类

  • FutureCallback定义了onSuccessonFailure方法,onSuccess方法会接收一个Future对象,这样我们就可以获取Future的结果。
  • 首先需要一个FutureCallback实现类。
/**
 * 定义一个FutureCallBack实现类
 */
public class FutureCallbackImpl implements FutureCallback<String> {
	private StringBuilder builder = new StringBuilder();

	@Override
	public void onSuccess(String result) {
		builder.append(result).append(" successfully");
	}

	@Override
	public void onFailure(Throwable t) {
		builder.append(t.toString());
	}

	public String getCallbackResult() {
		return builder.toString();
	}
}
使用实例:
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
ListenableFuture<String> futureTask = executorService.submit(new Callable<String>() { //创建ListenaleFuture对象
					@Override
					public String call() throws Exception {
						return "Task completed";
					}
				});
FutureCallbackImpl callback = new FutureCallbackImpl();
Futures.addCallback(futureTask, callback); //添加回调
callback.getCallbackResult(); //获取结果
如果CallBack是一个耗时操作,你应该选择另一个注册CallBack:
Futures.addCallback(futureTask,callback,executorService); //提供另一个线程池来执行性回调

SettableFuture类:

SettableFuture可以用来设置要返回得值:

SettableFuture<String> sf = SettableFuture.create();
//Set a value to return
sf.set("Success");
//Or set a failure Exception
sf.setException(someException);

AsyncFunction:

  • 该接口与函数式编程密切相关, 类似Function, 但apply方法会转换成一个ListenableFuture封装的范型对象。
public class AsyncFuntionSample implements AsyncFunction<Long, String> {
	private ConcurrentMap<Long, String> map = Maps.newConcurrentMap();
	private ListeningExecutorService listeningExecutorService;

	@Override
	public ListenableFuture<String> apply(final Long input) throws Exception {
		if (map.containsKey(input)) {
			SettableFuture<String> listenableFuture = SettableFuture.create(); //构建一个SettableFuture
			listenableFuture.set(map.get(input));
			return listenableFuture;
		} else {
			return listeningExecutorService.submit(new Callable<String>() {
				@Override
				public String call() throws Exception {
					String retrieved = //compute to get the data;
					map.putIfAbsent(input, retrieved);
					return retrieved;
				}
			});
		}
	}
}

FutureFallback类:

  • FutureFallback用于异常恢复的备份。
/**
 * 当Future任务失败后, 作为备份的Future
 */
public class FutureFallbackImpl implements FutureFallback<String> {
	@Override
	public ListenableFuture<String> create(Throwable t) throws Exception {
		if (t instanceof FileNotFoundException) {
			SettableFuture<String> settableFuture = SettableFuture.create();
			settableFuture.set("Not Found");
			return settableFuture;
		}
		throw new Exception(t);
	}
}

Futures类:

  • Futures类是有关Future实例的一个工具类。

异步转换:

ListenableFuture<Person> lf = Futures.transform(ListenableFuture<String> f,AsyncFunction<String,Person> af);

使用FutureFallbacks:

ListenableFuture<String> lf = Futures.withFallback(ListenableFuture<String> f,FutureFallback<String> fb);

RateLimiter:

  • RateLimiter限制访问每秒访问资源的线程数。有点类似信号量Semaphore。
RateLimiter limiter = RateLimiter.create(4.0); //每秒不超过4个任务被提交
limiter.acquire();  //请求RateLimiter, 超过permits会被阻塞
executor.submit(runnable); //提交任务
也有非阻塞式地尝试:
If(limiter.tryAcquire()){ //未请求到limiter则立即返回false
    doSomething();
}else{
    doSomethingElse();
}
不吝指正。

© 著作权归作者所有

ihaolin
粉丝 263
博文 164
码字总数 106524
作品 4
朝阳
高级程序员
私信 提问
加载中

评论(1)

疯狂的骑士
疯狂的骑士
写的不错 JDK8中的CompletableFuture已经支持了
Google Guava 笔记

一、引言 Guava 是 google 几个java核心类库的集合,包括集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common ...

qllinhongyu
2014/09/18
0
0
Google Guava 类库简介(1)

Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,包括 collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, 等等. 这......

十二缸帕萨特
2015/10/07
75
0
Google的Guava类库简介(转)

说明:信息虽然有点旧,至少可以先了解个大概。 Guava是一个Google的基于Java的类库集合的扩展项目,包括collections, caching, primitives support, concurrency libraries, common annotat...

easonjim
2017/11/01
0
0
Guava学习笔记:Google Guava 类库简介

Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,包括 collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, 等等. 这......

长平狐
2013/06/17
1K
0
Guava学习笔记 开篇(Google Guava 类库简介)

Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,包括 collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, 等等. 这......

heroShane
2014/02/12
293
0

没有更多内容

加载失败,请刷新页面

加载更多

OpenStack 简介和几种安装方式总结

OpenStack :是一个由NASA和Rackspace合作研发并发起的,以Apache许可证授权的自由软件和开放源代码项目。项目目标是提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台。OpenSta...

小海bug
昨天
7
0
DDD(五)

1、引言 之前学习了解了DDD中实体这一概念,那么接下来需要了解的就是值对象、唯一标识。值对象,值就是数字1、2、3,字符串“1”,“2”,“3”,值时对象的特征,对象是一个事物的具体描述...

MrYuZixian
昨天
6
0
数据库中间件MyCat

什么是MyCat? 查看官网的介绍是这样说的 一个彻底开源的,面向企业应用开发的大数据库集群 支持事务、ACID、可以替代MySQL的加强版数据库 一个可以视为MySQL集群的企业级数据库,用来替代昂贵...

沉浮_
昨天
7
0
解决Mac下VSCode打开zsh乱码

1.乱码问题 iTerm2终端使用Zsh,并且配置Zsh主题,该主题主题需要安装字体来支持箭头效果,在iTerm2中设置这个字体,但是VSCode里这个箭头还是显示乱码。 iTerm2展示如下: VSCode展示如下: 2...

HelloDeveloper
昨天
9
0
常用物流快递单号查询接口种类及对接方法

目前快递查询接口有两种方式可以对接,一是和顺丰、圆通、中通、天天、韵达、德邦这些快递公司一一对接接口,二是和快递鸟这样第三方集成接口一次性对接多家常用快递。第一种耗费时间长,但是...

程序的小猿
昨天
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部