Detailed examples of Java Executor framework

Most are by way of concurrent tasks performed to achieve.

There are generally two ways to perform tasks: serial and parallel.

class SingleThreadWebServer {
 public static void main(String[] args) throws Exception {
  ServerSocket socket = new ServerSocket(80);
  while(true) {
   Socket conn = socket.accept();
   handleRequest(conn);
  }
 }
}
class ThreadPerTaskWebServer {
 public static void main(String[] args) throws Exception {
  ServerSocket socket = new ServerSocket(80);
  while(true) {
   final Socket conn = socket.accept();
   Runnable task = new Runnable() {
    public void run() {
     handleRequest(conn);
    }
   };
   new Thread(task).start();
  }
 }
}

 

Of course, the above two methods is problematic. The problem is single-threaded concurrency be a bottleneck, multi-threaded version is unlimited creation of threads can lead to insufficient resources.

Executor framework

A task is a set of logical unit of work, and the thread is to make the task asynchronous execution mechanism.

JDK provides the Executor interface:

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

Although the Executor interface is relatively simple, but it is the foundation of asynchronous task execution framework, the framework can support a variety of different types of task execution policy. It provides a standard way to process and submit the task execution process of decoupling. Represented by Runnable task. Executor implementation provides support and statistical information about the application management mechanism of the life cycle.

Executor is based producer-consumer model, the operation is equivalent to submit the task thread producers, perform tasks equivalent to consumption.

Based WebServer Examples Executor follows:

public class TaskExecutorWebServer {
 private static final int NTHREADS = 100;
 private static final Executor exec = Executors.newFixedThreadPool(NTHREADS);
 public static void main(String[] args) throws Exception {
  ServerSocket serverSocket = new ServerSocket(80);
  while (true) {
   final Socket conn = serverSocket.accept();
   Runnable task = new Runnable() {
    @Override
    public void run() {
     handleRequest(conn);
    }
   };
   exec.execute(task);
  }
 }
}

You may additionally realize his Executor controlled concurrent or parallel, as in the following code:

/ ** 
 * Perform Runnable tasks submitted objects. 
 * This interface provides a mechanism for job submission and how each task will be run (including details of thread use, scheduling, etc.) separated from the method. 
 * Executor often used instead of explicitly creating threads. 
 * 
 * 
 * @Author renchunxiao 
 * 
 * / 
public  class ExecutorDemo {
  public  static  void main (String [] args) { 
  the Executor Executor = new new ThreadExecutor (); 
  Executor.execute ( new new the Runnable () { 
   @Override 
   public  void RUN () {
     / / do something 
   } 
  }); 
  the Executor executor2 = new new SerialExecutor();
  executor2.execute(new Runnable() {
   @Override
   public void run() {
    // do something
   }
  });
 }
}
/**
 * 创建一个线程来执行 command
 *
 * @author renchunxiao
 *
 */
class ThreadExecutor implements Executor {
 @Override
 public void execute(Runnable command) {
  new Thread(command).start();
 }
}
/**
 * 串行执行 command
 *
 * @author renchunxiao
 *
 */
class SerialExecutor implements Executor {
 @Override
 public void execute(Runnable command) {
  command.run();
 }
}

Thread Pool

Thread pool thread is a resource pool, you can create a thread pool Executors static factory method.

  • newFixedThreadPool. Thread pool that creates fixed length, each commit task to create a thread until it reaches the maximum number of thread pool, thread pool size does not change.
  • newSingleThreadExecutor. Single thread pool.
  • newCachedThreadPool. According to the scale of the task changes the thread pool.
  • newScheduledThreadPool. Create a thread pool of fixed length, so as to delay or time to perform the task.

JVM will only quit when all non-daemon threads terminate all, so if you can not correctly closed Executor, then the JVM will not end.

To solve the problem of the life cycle of execution services, has extended Executor interface, a new interface ExecutorService.

public interface ExecutorService extends Executor {
 void shutdown();
 List<Runnable> shutdownNow();
 boolean isShutdown();
 boolean isTerminated();
 boolean awaitTermination(long timeout, TimeUnit unit)
  throws InterruptedException;
 <T> Future<T> submit(Callable<T> task);
 <T> Future<T> submit(Runnable task, T result);
 Future<?> submit(Runnable task);
 <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
  throws InterruptedException;
 <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
         long timeout, TimeUnit unit)
  throws InterruptedException;
 <T> T invokeAny(Collection<? extends Callable<T>> tasks)
  throws InterruptedException, ExecutionException;
 <T> T invokeAny(Collection<? extends Callable<T>> tasks,
     long timeout, TimeUnit unit)
  throws InterruptedException, ExecutionException, TimeoutException;
}

ExecutorService life cycle has three states: running, closed, has been terminated. ExecutorService is running at the time of initial creation. shutdown method will gently off: not to accept the new task, and wait for the completion of task execution has been carried out (including those not yet begun the task). shutdownNow method brutal off: it attempts to cancel all running tasks, and task queue has not yet started will not start. After completing all tasks are executed into the terminated state.

Callable 和 Future

Executor framework uses Runnable as the basic task of representation. Runnable is an abstract limitations, it can not return value and the run method throws an exception inspected.

Many tasks are actually calculate the delay of existence, such as database queries, access to resources from the network. For these tasks, a Callable is better abstraction, in its view call will return a value, and may throw an exception.

Executor task execution has four life cycle stages: creation, submission, start and finish. Because some tasks take a long time there may want to cancel, in which Executor framework has been submitted to the task is not started can be canceled.

Future represents the life cycle of a task, and provides a corresponding method to determine whether completed or canceled, and get the results of the task and cancel tasks.

https://mp.weixin.qq.com/s/vkvYJnKfQyuUeD_BDQy_1g

For more learning materials, you can scan the next Fanger Wei code

 

Guess you like

Origin www.cnblogs.com/lemonrel/p/11699616.html