BiBi - 并发编程 -15- Executor框架

2019-12-10  本文已影响0人  奋飞的蜗牛ing

From:Java并发编程的艺术

Java1.5之后把线程的工作单元和执行机制进行了分离。工作单元包括Runnable【无结果返回】和Callable【有结果返回】,执行机制由Executor框架提供。
Executor可以把一个Runnable对象封装为一个Callable对象。

ThreadPoolExecutor
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) { }
FixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
SingleThreadExecutor
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

SingleThreadExecutor和FixedThreadPool就前两个参数不一样。

CachedThreadPool
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

使用SynchronousQueue没有容量的队列,每个插入操作必须等待另一个线程的对应移除操作。CachedThreadPool使用SynchronousQueue,把主线程提交的任务传递给空闲线程来执行【在60秒内】。

ScheduledThreadPoolExecutor
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue());
    }

ScheduledThreadPoolExecutor继承ThreadPoolExecutor。DelayQueue是一个无界队列,它里面封装了一个PriorityQueue,会按照时间先后顺序进行排序,如果时间相同,则再按照任务添加的先后顺序。
执行过程:先从DelayQueue中获取已到期的ScheduleFutureTask进行执行,然后修改这个任务的time变量为下次执行的时间,最后将修改time后的ScheduleFutureTask放回到DelayQueue中。

FutureTask 异步计算结果

FutureTask继承了Future接口和Runnable接口。
构造函数:

FutureTask(Callable<V> callable) { }
FutureTask(Runnable runnable, V result) { }

开启线程的方法:

//方法一:继承于Thread
new Thread() {
  @Override
  public void run() {
  }
}.start();

//方法二:实现Runnable接口
new Thread(new Runnable() {
  @Override
  public void run() {

  }
}).start();

//方法三:FutureTask + Callable, 有结果返回
FutureTask<String> res = new FutureTask<String>(new Callable<String>() {
  @Override
  public String call() throws Exception {
    return null;
  }
}).run();

//方法四:FutureTask + Runnable, 有结果返回
String result = null;
new FutureTask<String>(new Runnable() {
  @Override
  public void run() {

  }
}, result).run();

注意:FutureTask调用run方法启动线程而不是start方法。

FutureTask使用场景:当一个线程需要等待另一线程把某个任务执行完后才能继续执行。
FutureTask的实现基于AQS同步器。FutureTask的acquire操作对应为get()/get(long timeout);release操作对应为run方法或cancel方法。

上一篇 下一篇

猜你喜欢

热点阅读