Java-多线程框架Executor

简介: Java-多线程框架Executor



概述

在Java中,使用线程来异步执行任务。Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源。同时,为每一个任务创建一个新线程来执行,这种策略可能会使处于高负荷状态的应用最终崩溃。

Java线程既是工作单元,也是执行单元。从JDK1.5开始,把工作单元与执行机制分离开来。工作单元包括Runnable 和 Callable,而执行机制由Executor框架提供。

Java从1.5版本开始,为简化多线程并发编程,引入全新的并发编程包:java.util.concurrent及其并发编程框架(Executor框架)。

Executor框架是指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等。

类关系图如下:

在Executor框架中,使用执行器(Exectuor)来管理Thread对象,从而简化了并发编程。


Executor框架简介

Executor框架的两级调度模型

在HotSpot VM的线程模型中,Java线程被一对一映射为本地操作系统线程。

Java线程启动时会创建一个本地操作系统线程;当Java线程终止时,这个操作系统线程也会被回收。操作系统会调用所有线程并将他们分配给可用的CPU。

可以将此种模式分为两层

  • 在上层,Java多线程程序通常把应用程序分解为若干任务,然后使用用户级的调度器(Executor框架)将这些任务映射为固定数量的线程
  • 在底层,操作系统内核将这些线程映射到硬件处理器上。

两级调度模型的示意图如下:

从图中可以看出,该框架用来控制应用程序的上层调度,下层调度由操作系统内核控制,不受应用程序控制.


Executor框架成员

任务

被执行任务需要实现的接口:Runnable接口和Callable接口

执行任务

任务执行机制的核心接口Executor,以及继承自Executor的ExecutorService接口。

Executor框架有两个关键类实现了ExecutorService接口:ThreadPoolExecutor 和 ScheduledThreadPoolExector.

异步计算的结果

Future和实现Future接口的FutureTask类。


Executor框架的类与接口

  • Executor是一个接口,Executor框架的基础,它将任务的提交与任务的执行分离。
  • Executors 线程池工厂类
  • AbstractExecutorService 执行框架抽象类。
  • ThreadPoolExecutor是线程池的核心实现类,用来执行被提交的任务。
  • ScheduledThreadPoolExecutor是一个实现类,可以在给定的延迟后运行命令,或者定期执行命令。ScheduledThreadPoolExecutor 比 Timer 更灵活,功能更强大。
  • Future接口和它的实现FutureTask类,代表异步计算的结果。
  • Runnable和Callable接口的实现类,都可以被ThreadPoolExecutor 或 ScheduledThreadPoolExecutor执行.

使用Executor框架

1。 主线程首先要创建实现 Runnable接口或者Callable接口的任务对象。Executors可以把一个Runnable对象封装为一个Callable对象,如下

Executors.callable(Runnale task);

或者

Executors.callable(Runnable task, Object result);

2。 然后把Runnable对象直接交给ExecutorService执行

ExecutorService.execute(Runnable command);

或者也可以把Runnable对象或Callable对象提交给ExecutorService执行。 如果执行ExecutorService.submit(…),ExecutorService将返回一个实现Future接口的对象(到目前为止的JDK中,返回的是FutureTask对象)。由于FutureTask实现了Runnable接口,我们也可以创建FutureTask类,然后直接交给ExecutorService执行。

ExecutorService.submit(Runnable task);

3。 最后,主线程可以执行FutureTask.get()方法来等待任务执行完成。主线程也可以执行FutureTask.cancel(boolean mayInterruptIfRunning)来取消此任务的执行。


Executors 工厂方法

JDK内部提供了五种最常见的线程池。由Executors类的五个静态工厂方法创建

  • newFixedThreadPool
  • newSingleThreadExecutor
  • newCachedThreadPool
  • newSingleThreadScheduledExecutor
  • newScheduledThreadPool

newFixedThreadPool 固定大小的线程池

我们来看下源码及注释

只有一个入参nThreads的静态方法

/**
     * Creates a thread pool that reuses a fixed number of threads
     * operating off a shared unbounded queue.  At any point, at most
     * <tt>nThreads</tt> threads will be active processing tasks.
     * If additional tasks are submitted when all threads are active,
     * they will wait in the queue until a thread is available.
     * If any thread terminates due to a failure during execution
     * prior to shutdown, a new one will take its place if needed to
     * execute subsequent tasks.  The threads in the pool will exist
     * until it is explicitly {@link ExecutorService#shutdown shutdown}.
     *
     * @param nThreads the number of threads in the pool
     * @return the newly created thread pool
     * @throws IllegalArgumentException if {@code nThreads <= 0}
     */
   public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

两个入参nThreads和threadFactory的静态方法

/**
     * Creates a thread pool that reuses a fixed number of threads
     * operating off a shared unbounded queue, using the provided
     * ThreadFactory to create new threads when needed.  At any point,
     * at most <tt>nThreads</tt> threads will be active processing
     * tasks.  If additional tasks are submitted when all threads are
     * active, they will wait in the queue until a thread is
     * available.  If any thread terminates due to a failure during
     * execution prior to shutdown, a new one will take its place if
     * needed to execute subsequent tasks.  The threads in the pool will
     * exist until it is explicitly {@link ExecutorService#shutdown
     * shutdown}.
     *
     * @param nThreads the number of threads in the pool
     * @param threadFactory the factory to use when creating new threads
     * @return the newly created thread pool
     * @throws NullPointerException if threadFactory is null
     * @throws IllegalArgumentException if {@code nThreads <= 0}
     */
   public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }

每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

该方法返回一个包含指定数目线程的线程池,如果任务数量多于线程数目,那么没有没有执行的任务必须等待,直到有任务完成为止。


newSingleThreadExecutor 单线程的线程池

/**
     * Creates an Executor that uses a single worker thread operating
     * off an unbounded queue. (Note however that if this single
     * thread terminates due to a failure during execution prior to
     * shutdown, a new one will take its place if needed to execute
     * subsequent tasks.)  Tasks are guaranteed to execute
     * sequentially, and no more than one task will be active at any
     * given time. Unlike the otherwise equivalent
     * <tt>newFixedThreadPool(1)</tt> the returned executor is
     * guaranteed not to be reconfigurable to use additional threads.
     *
     * @return the newly created single-threaded Executor
     */
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
/**
     * Creates an Executor that uses a single worker thread operating
     * off an unbounded queue, and uses the provided ThreadFactory to
     * create a new thread when needed. Unlike the otherwise
     * equivalent <tt>newFixedThreadPool(1, threadFactory)</tt> the
     * returned executor is guaranteed not to be reconfigurable to use
     * additional threads.
     *
     * @param threadFactory the factory to use when creating new
     * threads
     *
     * @return the newly created single-threaded Executor
     * @throws NullPointerException if threadFactory is null
     */
    public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }

这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。

返回单线程的Executor,将多个任务交给此Exector时,这个线程处理完一个任务后接着处理下一个任务,若该线程出现异常,将会有一个新的线程来替代。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

说明:LinkedBlockingQueue会无限的添加需要执行的Runnable。


newCachedThreadPool 可缓存的线程池

/**
     * Creates a thread pool that creates new threads as needed, but
     * will reuse previously constructed threads when they are
     * available.  These pools will typically improve the performance
     * of programs that execute many short-lived asynchronous tasks.
     * Calls to <tt>execute</tt> will reuse previously constructed
     * threads if available. If no existing thread is available, a new
     * thread will be created and added to the pool. Threads that have
     * not been used for sixty seconds are terminated and removed from
     * the cache. Thus, a pool that remains idle for long enough will
     * not consume any resources. Note that pools with similar
     * properties but different details (for example, timeout parameters)
     * may be created using {@link ThreadPoolExecutor} constructors.
     *
     * @return the newly created thread pool
     */
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
/**
     * Creates a thread pool that creates new threads as needed, but
     * will reuse previously constructed threads when they are
     * available, and uses the provided
     * ThreadFactory to create new threads when needed.
     * @param threadFactory the factory to use when creating new threads
     * @return the newly created thread pool
     * @throws NullPointerException if threadFactory is null
     */
    public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>(),
                                      threadFactory);
    }

如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

newCachedThreadPool方法创建的线程池可以自动的扩展线程池的容量。核心线程数量为0。

SynchronousQueue是个特殊的队列。 SynchronousQueue队列的容量为0。当试图为SynchronousQueue添加Runnable,则执行会失败。只有当一边从SynchronousQueue取数据,一边向SynchronousQueue添加数据才可以成功。SynchronousQueue仅仅起到数据交换的作用,并不保存线程。但newCachedThreadPool()方法没有线程上限。Runable添加到SynchronousQueue会被立刻取出。

根据用户的任务数创建相应的线程来处理,该线程池不会对线程数目加以限制,完全依赖于JVM能创建线程的数量,可能引起内存不足。


newSingleThreadScheduledExecutor

/**
     * Creates a single-threaded executor that can schedule commands
     * to run after a given delay, or to execute periodically.
     * (Note however that if this single
     * thread terminates due to a failure during execution prior to
     * shutdown, a new one will take its place if needed to execute
     * subsequent tasks.)  Tasks are guaranteed to execute
     * sequentially, and no more than one task will be active at any
     * given time. Unlike the otherwise equivalent
     * <tt>newScheduledThreadPool(1)</tt> the returned executor is
     * guaranteed not to be reconfigurable to use additional threads.
     * @return the newly created scheduled executor
     */
    public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1));
    }
/**
     * Creates a single-threaded executor that can schedule commands
     * to run after a given delay, or to execute periodically.  (Note
     * however that if this single thread terminates due to a failure
     * during execution prior to shutdown, a new one will take its
     * place if needed to execute subsequent tasks.)  Tasks are
     * guaranteed to execute sequentially, and no more than one task
     * will be active at any given time. Unlike the otherwise
     * equivalent <tt>newScheduledThreadPool(1, threadFactory)</tt>
     * the returned executor is guaranteed not to be reconfigurable to
     * use additional threads.
     * @param threadFactory the factory to use when creating new
     * threads
     * @return a newly created scheduled executor
     * @throws NullPointerException if threadFactory is null
     */
    public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1, threadFactory));
    }

该线程池支持定时以及周期性执行任务的需求。


newScheduledThreadPool 定时任务调度的线程池

/**
     * Creates a thread pool that can schedule commands to run after a
     * given delay, or to execute periodically.
     * @param corePoolSize the number of threads to keep in the pool,
     * even if they are idle.
     * @return a newly created scheduled thread pool
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     */
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
/**
     * Creates a thread pool that can schedule commands to run after a
     * given delay, or to execute periodically.
     * @param corePoolSize the number of threads to keep in the pool,
     * even if they are idle.
     * @param threadFactory the factory to use when the executor
     * creates a new thread.
     * @return a newly created scheduled thread pool
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     * @throws NullPointerException if threadFactory is null
     */
    public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }

创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。


实例

newFixedThreadPool示例

package com.xgj.master.java.executor.newFixedThreadPool;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.junit.Test;
/**
 * 
 * 
 * @ClassName: NewFixedThreadPoolDemo
 * 
 * @Description: NewFixedThreadPool
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月3日 下午9:09:25
 */
public class NewFixedThreadPoolDemo {
  @Test
  public void test() {
    // 通过Executors的静态方法创建一个包含2个固定线程的线程池
    ExecutorService fixPool = Executors.newFixedThreadPool(2);
    // 第一种形式:通过Callable匿名内部类的形式 创建执行对象
    Callable<String> callable = new Callable<String>() {
      String result = "Bussiness deals successfully";
      @Override
      public String call() throws Exception {
        System.out.println("Callable is working");
        Thread.sleep(5 * 1000);
        System.out.println("Callable some bussiness logic is here ");
        return result;
      }
    };
    // 第二种形式:通过Runna匿名内部类的形式 创建执行对象
    Runnable runnable = new Runnable() {
      @Override
      public void run() {
        try {
          System.out.println("Runnable is  working");
          Thread.sleep(5 * 1000);
          System.out.println("Runnable some bussiness logic is here ");
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    };
    // 提交两个不同形式创建的任务 (因为创建了2个固定线程的线程池,所以两个都可以提交,如果只有一个线程的话,第二个必须等待
    // 任务数量多于线程数目,那么没有没有执行的任务必须等待,直到有任务完成为止。
    // Future<> gets parameterized based on how Callable is parameterized
    // Since Runnable is not parameterized, you get a Future <?>
    Future<String> callableFuture = fixPool.submit(callable);
    Future<?> runnableFuture = fixPool.submit(runnable);
    // check if tasks are done or not
    if (callableFuture.isDone()) {
      System.out.println("\t\tCallable is done !");
    } else {
      System.out.println("\t\tCallable is not done !");
    }
    if (runnableFuture.isDone()) {
      System.out.println("\t\tRunnable is done !");
    } else {
      System.out.println("\t\tRunnable is not done !");
    }
    // callableFuture有返回值,获取返回值,runnable没有返回值
    try {
      String result = callableFuture.get();
      System.out.println("CallableFuture的返回值为:" + result);
    } catch (InterruptedException e) {
      e.printStackTrace();
    } catch (ExecutionException e) {
      e.printStackTrace();
    }
    // 根据需要决定是否需要关闭线程池
    fixPool.shutdown();
    System.out.println("fixPool shutdown");
  }
}

运行结果:

Callable is not done !
Callable is working
    Runnable is not done !
Runnable is  working
Callable some bussiness logic is here 
Runnable some bussiness logic is here 
CallableFuture的返回值为:Bussiness deals successfully
fixPool shutdown

newSingleThreadExecutor示例

package com.xgj.master.java.executor.newSingleThreadExecutor;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
/**
 * 
 * 
 * @ClassName: NewSingleThreadExecutorDemo
 * 
 * @Description: newSingleThreadExecutor() returns ExecutorService with one
 *               thread pool size. ExecutorService uses single thread to execute
 *               the task. Other task will wait in queue. If thread is
 *               terminated or interrupted, a new thread will be created.
 *               ExecutorService guarantees to finish the task if not shutdown
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月3日 下午9:57:56
 */
public class NewSingleThreadExecutorDemo {
  @Test
  public void test() throws InterruptedException, ExecutionException {
    // creates thread pool with one thread
    ExecutorService newSingleThreadPool = Executors.newSingleThreadExecutor();
    // callable thread starts to execute
    Future<Integer> callableFuture = newSingleThreadPool
        .submit(new NewSingleThreadExecutorDemo().new CallableThread());
    // gets value of callable thread
    int callval = callableFuture.get();
    System.out.println("Callable:" + callval);
    // checks for thread termination
    boolean isTerminated = newSingleThreadPool.isTerminated();
    System.out.println("newSingleThreadPool  isTerminated :" + isTerminated);
    // waits for termination for 10 seconds only
    newSingleThreadPool.awaitTermination(10, TimeUnit.SECONDS);
    newSingleThreadPool.shutdownNow();
    System.out.println("newSingleThreadPool shutdownNow ");
  }
  /**
   * 
   * 
   * @ClassName: CallableThread
   * 
   * @Description: 内部类, Callable泛型类的入参假设为Integer
   * 
   * @author: Mr.Yang
   * 
   * @date: 2017年9月3日 下午11:05:25
   */
  class CallableThread implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
      int cnt = 0;
      for (; cnt < 5; cnt++) {
        Thread.sleep(5 * 1000);
        System.out.println("call:" + cnt);
      }
      return cnt;
    }
  }
}

运行结果

call:0
call:1
call:2
call:3
call:4
Callable:5
newSingleThreadPool  isTerminated :false
newSingleThreadPool shutdownNow 

newCachedThreadPool示例

package com.xgj.master.java.executor.newCachedThreadPool;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.junit.Test;
/**
 * 
 * 
 * @ClassName: NewCachedThreadPoolDemo
 * 
 * @Description: 1.The pool creates new threads if needed but reuses previously
 *               constructed threads if they are available.
 * 
 *               2.Cached thread pool helps improve the performance of
 *               applications that make many short-lived asynchronous tasks.
 * 
 *               3.Only if no threads are available for reuse will a new thread
 *               be created and added to the pool.
 * 
 *               4.Threads that have not been used for more than sixty seconds
 *               are terminated and removed from the cache. Hence a pool which
 *               has not been used long enough will not consume any resources.
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月3日 下午11:15:05
 */
public class NewCachedThreadPoolDemo {
  @Test
  public void test() {
    // Obtain a cached thread pool
    ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    // Create an anonymous Callable<T> object.Override call()
    Callable<String> callable = new Callable<String>() {
      String message = "Callable is done !";
      @Override
      public String call() throws Exception {
        for (int i = 0; i < 10; i++) {
          System.out.println("Callable is doing something");
          Thread.sleep(500); // make it sleep a little
        }
        return message;
      }
    };
    // Create an anonymous instance of Runnable
    Runnable runnable = new Runnable() {
      @Override
      public void run() {
        try {
          for (int i = 0; i < 10; i++) {
            System.out.println("\tRunnable is doing something");
            Thread.sleep(1000);
          }
        } catch (Exception e) {
        }
      }
    };
    // Time to run these
    // Future<> gets parameterized based on how Callable is parameterized
    // Since Runnable is not parameterized, you get a Future <?>
    Future<String> callableFuture = cachedThreadPool.submit(callable);
    Future<?> runnableFuture = cachedThreadPool.submit(runnable);
    // check if tasks are done or not
    if (callableFuture.isDone()) {
      System.out.println("\t\tCallable is done !");
    } else {
      System.out.println("\t\tCallable is not done !");
    }
    if (runnableFuture.isDone()) {
      System.out.println("\t\tRunnable is done !");
    } else {
      System.out.println("\t\tRunnable is not done !");
    }
    try {
      // get() waits for the task to finish and then gets the result
      String returnedValue = callableFuture.get();
      System.out.println(returnedValue);
    } catch (InterruptedException e) {
      // thrown if task was interrupted before completion
      e.printStackTrace();
    } catch (ExecutionException e) {
      // thrown if the task threw an execption while executing
      e.printStackTrace();
    }
    // shutdown the pool if needed.
    cachedThreadPool.shutdown();
  }
}

运行结果

Callable is not done !
    Runnable is not done !
Callable is doing something
  Runnable is doing something
Callable is doing something
Callable is doing something
  Runnable is doing something
Callable is doing something
  Runnable is doing something
Callable is doing something
Callable is doing something
  Runnable is doing something
Callable is doing something
Callable is doing something
  Runnable is doing something
Callable is doing something
Callable is doing something
  Runnable is doing something
Callable is done !

newSingleThreadScheduledExecutor示例

package com.xgj.master.java.executor.newSingleThreadScheduledExecutor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
 * 
 * 
 * @ClassName: NewSingleThreadScheduleExectorDemo
 * 
 * @Description: scheduleSingleThreadPool
 *              更多方法的使用: http://www.codejava.net/java-core/concurrency/java-concurrency-
 *               scheduling-tasks-to-execute-after-a-given-delay-or-periodically
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月3日 下午11:48:47
 */
public class NewSingleThreadScheduleExectorDemo {
  private static String threadNamePrefix = "XiaoGongJiang";
  public static void main(String[] args) {
    // Get the scheduler
    ScheduledExecutorService scheduleSingleThreadPool = Executors
        .newSingleThreadScheduledExecutor(new ThreadFactory() {
          public Thread newThread(Runnable r) {
            return new Thread(r, "Thread-" + threadNamePrefix);
          }
        });
    // Create an anonymous instance of Runnable
    Runnable runnable = new Runnable() {
      @Override
      public void run() {
        try {
          System.out.println("Begin");
          for (int i = 0; i < 3; i++) {
            System.out.println("\tRunnable is doing something");
            Thread.sleep(1000);
          }
        } catch (Exception e) {
          System.out.println(e.getMessage());
        }
      }
    };
    // Get a handle, starting now, with a 2 seconds delay,
    // and run at fixed rate (5 seconds)
    scheduleSingleThreadPool.scheduleAtFixedRate(runnable, 2, 5, TimeUnit.SECONDS);
  }
}

运行结果:

Begin
  Runnable is doing something
  Runnable is doing something
  Runnable is doing something
Begin
  Runnable is doing something
  Runnable is doing something
  Runnable is doing something
Begin
  ........

等上个任务处理完成后,紧接着处理下一个,一直循环下去。

两个方法的区别:

  • scheduleAtFixedRate ,以固定的频率来执行某个任务。
  • scheduleWithFixedDealy, 相对固定的延迟后,执行某个任务。

newScheduledThreadPool示例

package com.xgj.master.java.executor.newScheduledThreadPool;
import java.text.DateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
 * 
 * 
 * @ClassName: NewScheduledThreadPoolDemo
 * 
 * @Description:三个常用方法 1.schedule(): This allows you to schedule a Callable or a
 *                     Runnable for one-shot execution after a specified delay.
 * 
 *                     2.scheduleAtFixedRate(): This lets you schedule tasks
 *                     that will first execute after a specified delay and then
 *                     will execute again based on the period you specified. If
 *                     you set the initial delay for five seconds and then
 *                     subsequent period to five seconds then your task will
 *                     first execute five seconds after the first submission and
 *                     then will execute periodically every five seconds.
 * 
 *                     3.scheduleWithFixedDelay(): This lets you create tasks
 *                     that will first be executed after the initial delay then
 *                     subsequently with given delay between the termination of
 *                     one execution and commencement of another execution. So
 *                     if you create a task with initial delay of five seconds
 *                     and the subsequent delay of five seconds, the task will
 *                     be executed five seconds after the submission. Once the
 *                     task finishes execution, the scheduler will wait for five
 *                     seconds and then execute the task again.
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月4日 上午12:24:31
 */
public class NewScheduledThreadPoolDemo {
  final static DateFormat fmt = DateFormat.getTimeInstance(DateFormat.LONG);
  public static void main(String[] args) {
    // Create a scheduled thread pool with 5 core threads
    ScheduledThreadPoolExecutor sch = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(5);
    // Create a task for one-shot execution using schedule()
    Runnable oneShotTask = new Runnable() {
      @Override
      public void run() {
        System.out.println("\t oneShotTask Execution Time: " + fmt.format(new Date()));
      }
    };
    // Create another task
    Runnable delayTask = new Runnable() {
      @Override
      public void run() {
        try {
          System.out.println("\t delayTask Execution Time: " + fmt.format(new Date()));
          Thread.sleep(10 * 1000);
          System.out.println("\t delayTask End Time: " + fmt.format(new Date()));
        } catch (Exception e) {
        }
      }
    };
    // And yet another
    Runnable periodicTask = new Runnable() {
      @Override
      public void run() {
        try {
          System.out.println("\t periodicTask Execution Time: " + fmt.format(new Date()));
          Thread.sleep(10 * 1000);
          System.out.println("\t periodicTask End Time: " + fmt.format(new Date()));
        } catch (Exception e) {
        }
      }
    };
    System.out.println("Submission Time: " + fmt.format(new Date()));
    // ScheduledFuture<?> oneShotFuture = sch.schedule(oneShotTask, 5,
    // TimeUnit.SECONDS);
    // ScheduledFuture<?> delayFuture =
    // sch.scheduleWithFixedDelay(delayTask, 5, 5, TimeUnit.SECONDS);
    ScheduledFuture<?> periodicFuture = sch.scheduleAtFixedRate(periodicTask, 5, 5, TimeUnit.SECONDS);
  }
}
Submission Time: 上午12时26分27秒
   periodicTask Execution Time: 上午12时26分32秒
   periodicTask End Time: 上午12时26分42秒
   periodicTask Execution Time: 上午12时26分42秒
   periodicTask End Time: 上午12时26分52秒
   periodicTask Execution Time: 上午12时26分52秒
   periodicTask End Time: 上午12时27分02秒
   periodicTask Execution Time: 上午12时27分02秒
   .........
   .........


相关文章
|
23小时前
|
安全 Java 调度
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第12天】 在现代软件开发中,多线程编程是提升应用程序性能和响应能力的关键手段之一。特别是在Java语言中,由于其内置的跨平台线程支持,开发者可以轻松地创建和管理线程。然而,随之而来的并发问题也不容小觑。本文将探讨Java并发编程的核心概念,包括线程安全策略、锁机制以及性能优化技巧。通过实例分析与性能比较,我们旨在为读者提供一套既确保线程安全又兼顾性能的编程指导。
|
23小时前
|
Java 程序员 调度
Java中的多线程编程:从理论到实践
【5月更文挑战第14天】在现代计算机技术中,多线程编程是一个重要的概念。它允许多个线程并行执行,从而提高程序的运行效率。本文将从理论和实践两个角度深入探讨Java中的多线程编程,包括线程的基本概念、创建和控制线程的方法,以及如何处理线程同步和通信问题。
|
23小时前
|
前端开发 Java Spring
Java Web ——MVC基础框架讲解及代码演示(下)
Java Web ——MVC基础框架讲解及代码演示
8 1
|
23小时前
|
设计模式 前端开发 网络协议
Java Web ——MVC基础框架讲解及代码演示(上)
Java Web ——MVC基础框架讲解及代码演示
6 0
|
23小时前
|
Java
Java中的多线程编程:基础知识与实践
【5月更文挑战第13天】在计算机科学中,多线程是一种使得程序可以同时执行多个任务的技术。在Java语言中,多线程的实现主要依赖于java.lang.Thread类和java.lang.Runnable接口。本文将深入探讨Java中的多线程编程,包括其基本概念、实现方法以及一些常见的问题和解决方案。
|
23小时前
|
安全 算法 Java
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第13天】 在Java开发中,并发编程是一个复杂且重要的领域。它不仅关系到程序的线程安全性,也直接影响到系统的性能表现。本文将探讨Java并发编程的核心概念,包括线程同步机制、锁优化技术以及如何平衡线程安全和性能。通过分析具体案例,我们将提供实用的编程技巧和最佳实践,帮助开发者在确保线程安全的同时,提升应用性能。
10 1
|
23小时前
|
Java 调度
Java一分钟之线程池:ExecutorService与Future
【5月更文挑战第12天】Java并发编程中,`ExecutorService`和`Future`是关键组件,简化多线程并提供异步执行能力。`ExecutorService`是线程池接口,用于提交任务到线程池,如`ThreadPoolExecutor`和`ScheduledThreadPoolExecutor`。通过`submit()`提交任务并返回`Future`对象,可检查任务状态、获取结果或取消任务。注意处理`ExecutionException`和避免无限等待。实战示例展示了如何异步执行任务并获取结果。理解这些概念对提升并发性能至关重要。
17 5
|
23小时前
|
Java
Java一分钟:线程协作:wait(), notify(), notifyAll()
【5月更文挑战第11天】本文介绍了Java多线程编程中的`wait()`, `notify()`, `notifyAll()`方法,它们用于线程间通信和同步。这些方法在`synchronized`代码块中使用,控制线程执行和资源访问。文章讨论了常见问题,如死锁、未捕获异常、同步使用错误及通知错误,并提供了生产者-消费者模型的示例代码,强调理解并正确使用这些方法对实现线程协作的重要性。
15 3
|
8月前
|
SQL Java 数据库连接
Java面试题日积月累(SSM框架面试题22道)
Java面试题日积月累(SSM框架面试题22道)
55 0
|
6月前
|
缓存 Java 开发工具
Java面试题 -其他框架
Java面试题 -其他框架
39 0