java.util.concurrent学习笔记

concurrent在线文档:

http://www.cjsdn.net/Doc/JDK50/java/util/concurrent/Executors.html

http://www.cjsdn.net/Doc/JDK50/java/util/concurrent/ScheduledExecutorService.html

 

java.util.concurrent包主要接口和类:

Executor:具体Runnable任务的执行者。
ExecutorService:一个线程池管理者,其实现类有多种,我会介绍一部分。我们能把Runnable,Callable提交到池中让其调度。
Semaphore:一个计数信号量
ReentrantLock:一个可重入的互斥锁定 Lock,功能类似synchronized,但要强大的多。
Future:是与Runnable,Callable进行交互的接口,比如一个线程执行结束后取返回的结果等等,还提供了cancel终止线程。
BlockingQueue:阻塞队列。
CompletionService: ExecutorService的扩展,可以获得线程执行结果的
CountDownLatch:一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 
CyclicBarrier:一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 
Future:Future 表示异步计算的结果。
ScheduledExecutorService :一个 ExecutorService,可安排在给定的延迟后运行或定期执行的命令。

 

下面主要介绍ScheduledExecutorService

ScheduledExecutorService
一个 ExecutorService,可安排在给定的延迟后运行或定期执行的命令。
schedule 方法使用各种延迟创建任务,并返回一个可用于取消或检查执行的任务对象。scheduleAtFixedRate 和 scheduleWithFixedDelay 方法创建并执行某些在取消前一直定期运行的任务。
用 Executor.execute(java.lang.Runnable) 和 ExecutorService 的 submit 方法所提交的命令,通过所请求的 0 延迟进行安排。
schedule 方法中允许出现 0 和负数延迟(但不是周期),并将这些视为一种立即执行的请求。
所有的 schedule 方法都接受相对 延迟和周期作为参数,而不是绝对的时间或日期。将以 Date 所表示的绝对时间转换成要求的形式很容易。
例如,要安排在某个以后的日期运行,可以使用:schedule(task, date.getTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS)。
但是要注意,由于网络时间同步协议、时钟漂移或其他因素的存在,因此相对延迟的期满日期不必与启用任务的当前 Date 相符。
Executors 类为此包中所提供的 ScheduledExecutorService 实现提供了便捷的工厂方法。

样例01:

许多长时间运行的应用有时候需要定时运行任务完成一些诸如统计、优化等工作,比如在电信行业中处理用户话单时,需要每隔1分钟处理话单;网站每天凌晨统计用户访问量、用户数;大型超时凌晨3点统计当天销售额、以及最热卖的商品;每周日进行数据库备份;公司每个月的10号计算工资并进行转帐等,这些都是定时任务。通过 java的并发库concurrent可以轻松的完成这些任务,而且非常的简单。

package com.amg.test;

import static java.util.concurrent.TimeUnit.SECONDS;

import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;

public class TestScheduledThread {
	public static void main(String[] args) {
		final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

		final Runnable beeper01 = new Runnable() {
			int count = 0;
			@Override
			public void run() {
				System.out.println(new Date() + " beep01 " + (++count));
			}
		};

		final Runnable beeper02 = new Runnable() {
			int count = 0;
			@Override
			public void run() {
				System.out.println(new Date() + " beep02 " + (++count));
			}
		};

		// 任务1:1秒钟后运行,并每隔2秒运行一次
		final ScheduledFuture beeperHandle01 = scheduler.scheduleAtFixedRate(beeper01, 1, 2, SECONDS);

		// 任务2:2秒钟后运行,并每次在上次任务运行完后等待5秒后重新运行
		final ScheduledFuture beeperHandle02 = scheduler.scheduleWithFixedDelay(beeper02, 2, 5, SECONDS);

		// 30秒后结束关闭任务,并且关闭Scheduler
		scheduler.schedule(new Runnable() {
			@Override
			public void run() {
				beeperHandle01.cancel(true);
				beeperHandle02.cancel(true);
				scheduler.shutdown();
			}
		}, 30, SECONDS);
	}
}

 为了退出进程,上面的代码中加入了关闭Scheduler的操作。而对于24小时运行的应用而言,是没有必要关闭Scheduler的。

样例02:

说明:下面的例子可实现以上同一功能:

package com.amg.test;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestScheduledThreadPoolExecutor {
	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	public static void main(String[] args) {
		ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
		System.out.println("thread start!!!");

		// scheduleAtFixedRate(Runnable对象,run方法执行的时候延迟?秒执行自己的方法,run方法执行时间间隔)
		exec.scheduleAtFixedRate(new Runnable() {// 每隔一段时间就触发异常
					@Override
					public void run() {
						// 执行自己的方法
						System.out.println("RuntimeException");
					}
				}, 3000, 5000, TimeUnit.MILLISECONDS);

		exec.scheduleAtFixedRate(new Runnable() {// 每隔一段时间打印系统时间,证明两者是互不影响的
					@Override
					public void run() {
						// 执行自己的方法
						System.out.println(sdf.format(new Date()));
					}
				}, 2000, 5000, TimeUnit.MILLISECONDS);
	}

}

猜你喜欢

转载自hejiajunsh.iteye.com/blog/1937949