public class learn {
static ExecutorService exe=Executors.newSingleThreadExecutor();
private volatile static boolean con=true;
public static void main(String []args){
TimeCycle(new Runnable() {
@Override
public void run() {
while(con){
System.out.println("Runing");
}
}},(long) 3,TimeUnit.SECONDS);
exe.shutdown();//不加则线程没有完全关闭,则无法退出
}
public static void TimeCycle(Runnable r,Long timeout,TimeUnit timeUnit){
Future<?> task=exe.submit(r);//该 Future 的 get 方法在成功 完成时将会返回 nul
try{
task.get(timeout,timeUnit);
}
catch(TimeoutException out){
con=false;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
finally{
task.cancel(true);//注意参数的不同带来的区别
}
}
}
一、Executor框架
1.Executor interface:此接口基于生产者-消费者模式,提供了一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法,可以对其任务提交方法进行重写使得任务提交后能够立即被运行、或者任务的连续性
//使用一个类来协作Excutor来使得任务被串行化
class SerialExecutor implements Executor {
final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
final Executor executor;
Runnable active;
SerialExecutor(Executor executor) {
this.executor = executor;
}
public synchronized void execute(final Runnable r) {
tasks.offer(new Runnable() {//向任务队列添加任务
public void run() {
try {
r.run();
} finally {
scheduleNext();//在事务执行结束后立即执行下一个任务
}
}
});
if (active == null) {//第一次提交任务时使得任务被连续执行
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((active = tasks.poll()) != null) {
executor.execute(active);
}
}
}
2.ExecutorService(extends Executor):提供了对Executor的生命周期进行管理的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法,其扩展了多个方法,如submit方法来提交任务并返回一个future对象、增加了批量任务执行的方法invokeAll、invokeAny(注意而这区别)、同时提供了两个方法来关闭其服务(区别)注意利用限时操作的方法来关闭线程
3.ScheduledExecutorService(extends ExecutorService):类似于Timer安排在给定的延迟后运行或定期执行的命令,但是是基于相对时间,而非Timer的绝对时间,可以使用此方法来代替Timer由于Timer只会创建一个线程来执行任务,可能会因为任务时间的原因导致任务的丢失。(可以利用Executors的工厂方法方便的获取其实例)
4.AbstractExecutorService,ScheduledThreadPoolExecutor,ThreadPoolExecutor均是ExecutorService的实现类,可以手动配置,但是建议使用Excutors的工厂方法,自定义时注意的点:
(1)队列任务的管理:即对排队任务的处理,使用怎样的队列队伍进行排队
(2)饱和策略:当任务队列被填满之后,线程池如何应对
5.Executors:用于实例化Excutor系列、ThreadFactory、Callable等的实用类,不存在继承关系
二、线程的关闭与取消
1.在例如Thread的sleep、wait及阻塞队列的阻塞时使用interrupte方法可以打断,它们能够检测中断的产生,并抛出异常,关闭中断标识,可以使用中断来关闭线程
2.通过Future来实现取消
public class learn {
static ExecutorService exe=Executors.newSingleThreadExecutor();
private volatile static boolean con=true;
public static void main(String []args){
TimeCycle(new Runnable() {
@Override
public void run() {
while(con){
System.out.println("Runing");
}
}},(long) 3,TimeUnit.SECONDS);
exe.shutdown();//不加则线程没有完全关闭,则无法退出
}
public static void TimeCycle(Runnable r,Long timeout,TimeUnit timeUnit){
Future<?> task=exe.submit(r);//该 Future 的 get 方法在成功 完成时将会返回 nul
try{
task.get(timeout,timeUnit);
}
catch(TimeoutException out){
con=false;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
finally{
task.cancel(true);//注意参数的不同带来的区别
}
}
}
3.其他方法可以通过标志对象、标志位或者使用单独线程进行取消。注意利用interrupt方法结合能够被中断的限时或阻塞进行取消。
三、显式锁:
1.Lock(interface):该接口提供了关于锁的尝试性操作以减少阻塞带来的死锁
2.ReentrantLock:Lock的一个实现,是一个可重入的互斥锁,且该类接受一个可选的公平参数
3.ReentrantReadWriteLock:ReadWriteLock接口的实现,其读锁可以由多个线程共享,而写锁只能独占
4.Condition:提供了同Object监视器类的协同方法,以便于与其绑定的Lock进行协作
一个利用Condition进行条件协作的例子
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();//让出了锁,被唤醒之后会重新获取锁
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}