您当前的位置: 首页 >  Java

郭梧悠

暂无认证

  • 1浏览

    0关注

    402博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Java 线程池 Executor浅入浅出

郭梧悠 发布时间:2018-08-03 18:50:10 ,浏览量:1

基础无论什么时候都是很重要的,为了防止长期也业务代码就此废掉,博主决定长期研究下多线程的java基础知识,算是巩固。本系列博文博主会不定期更新且长期更新下去,水平不够,如有发现不当之处欢迎批评指正,共同学习。

通过本文你可以了解到: 1、顺序执行线程的方式 2、多个任务终止的方法 3、线程池的工作原理或者线程复用的原理。

今天就来简单介绍Executor这个东西,这玩意是什么呢?官方注释说的很明白:Executes the given command at some time in the future!就是在将来的某个时候执行一个命令。很抽象?上代码就知道了这玩意就是一个接口:

public interface Executor {
    void execute(Runnable command);
}

接口设计接单吧,无非就是提供了参数为Runnable的方法而已。就是一个接口而已,怎么实现还不是实现者说了算?(战略上藐视),那么你可以这么用它,:

//该代码来自Executor示例
class DirectExecutor implements Executor {
    public void execute(Runnable r) {
      r.run();
    }

   public void static main(String args[]){
     DirectExecutor de = new DirectExecutor();
     de.exectue(new Runnable() {
        void run(){
          System.out.println("哪个线程调用我,我就再哪个线程中执行")
        }
     });
   }
}


那么如果执行一个比较耗时的任务呢?开启线程啊!多简单的事儿,所以上述代码改动如下:

class ThreadPerTaskExecutor implements Executor {
    public void execute(Runnable r) {
      //单独开启一个线程执行
       new Thread(r).start();
    }

   public void static main(String args[]){
     ThreadPerTaskExecutor tte = new ThreadPerTaskExecutor();
     tte.exectue(new Runnable() {
        void run(){
          System.out.println("单独开启一个线程执行")
        }
     });
   }
}

上面的代码逻辑很简单,就是每次执行exectue方法的时候都开启一个线程来执行Runnable。随着exectue的多次调用,会开启很多线程,而且这些线程执行的顺序也是不定的。

所以问题来了:如果设计一个多个异步任务顺序执行的框架呢?也就是说让多个线程顺序执行,该怎么设计?顺序执行,先进先出,那么脑海中的一个数据结构就是队列了,所以代码改动如下:

class SerialExecutor implements Executor{
    //任务队列
    final Queue tasks = new ArrayDeque();
    //真正执行任务的代理对象
    final Executor executor;
    Runnable active;

    SerialExecutor(Executor executor) {
      this.executor = executor;
    }

    public void execute(final Runnable r) {
      //将任务添加到队列中
      tasks.add(new Runnable() {
        public void run() {
          try {
            r.run();
          } finally {
             //当前任务执行完毕后,在执行队列中下一个任务
            scheduleNext();
          }
        }
      });

      if (active == null) {
        scheduleNext();
      }
    }

    //从对列中获取任务并执行
    protected void scheduleNext() {
      if ((active = tasks.poll()) != null) {
        executor.execute(active);
      }
    }

}

设计理念也很简单,将要执行的任务或者Runnable加入到一个队列中,每次从队列中去一个任务交给一个线程(在此处为ThreadPerTaskExecutor)出执行,注意这里并没有对队列做一个循环遍历操作,而是在run方法后加一个finally,执行scheduleNext来取队列中的下一个任务Runnable。

那么你就可以这么调用:


    public static void main(){
        SerialExecutor serialExecutor=  new SerialExecutor(new ThreadPerTaskExecutor());
        for(int i=0;i            
关注
打赏
1663674776
查看更多评论
0.0401s