Task 1.

Abstract programs into multiple tasks.

2. Modern Web programs divide task boundaries

Border with individual customer requests. It’s one request, one task.

3. Task scheduling policies

3.1 Serial execution

Poor responsiveness and throughput.

3.2 Create a thread for each task

Conclusion:

  • Subthreads handle tasks, improving responsiveness and throughput.
  • Task-handling code must be thread-safe.

Inadequate:

  • The overhead of the thread lifecycle is very high.
  • Resource consumption. When there are more runnable threads than available processors, there are idle threads occupying memory, and there are other performance costs when a large number of threads compete for CPU.
  • Stability. There is a limit to the number of threads that can be created on different platforms.

4. Design of Executor framework in Java

4.1 Design Concept

Java provides the Executor framework to perform tasks. Based on the producer-consumer model. A submission task is an operation that acts as a producer, and a thread that executes the task acts as a consumer. (Decoupling, peak cutting)

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

4.2 Executing Policies

The task submission code is scattered throughout the program’s business code. The implementation strategy is handled by the framework.

The execution strategy defines “What,Where,When,How” and other aspects of task execution, including:

  • In What thread is the task executed?
  • In What order are tasks executed (priority)?
  • How Many tasks can be executed concurrently?
  • How Many tasks are waiting to be executed in the queue?
  • How does the system reject a task?
  • What should be done before and after a task?

By separating the task submission from the execution strategy of the task, it helps to select the execution strategy that best matches the available hardware resources during deployment.

4.3 the thread pool

The Executor task execution framework programs policies based on thread pools with the “assign one thread to each task” policy. The class library provides a flexible thread pool and some useful default configurations. Such as newFixedThreadpool.

  • Web servers no longer fail under high load.
  • But tasks always arrive faster than they can be executed, and the server can still run out of memory.

4.4Executor Life Cycle

Executor extends the ExecutorService interface by adding methods for lifecycle management.

Public Interface ExecutorService extends Executor {/** ** A smooth shutdown process: No new tasks are accepted and tasks that have already been committed are executed. */ void shutdown(); /** * Rough shutdown process: It will try to cancel all running tasks that are not in the startup queue and have not yet started execution. */ list<Runnable> shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit); }Copy the code

4.5 Delayed Tasks and Periodic Tasks

JAVA provides timers to manage scheduled tasks.

  • Only one thread is created for the Timer task.
  • Timer is a scheduling mechanism based on absolute time and is sensitive to system time.
  • The Timer has thread leak issues (the Timer does not catch exceptions and the thread terminates when an unchecked exception is thrown).

ScheduledThreadPoolExecutor better time management tasks.

  • Inside it is a thread pool.
  • It solves the thread leak problem of Timer well.

Not suitable for distributed environments.

5. Find available parallelism

This chapter provides examples to explore parallelism in a request.

5.1 Example: Serial page renderer

Assume page = text label + image the following code executes the render sequentially.

    public class SingleThreadRenderer {
        void renderPage(CharSequence source) {
            renderText(source);
            List<ImageData> imageData = new ArrayList<ImageData>();
            for (ImageInfo imageInfo : scanForImageInfo(source))
                imageData.add(imageInfo.downloadImage());
            for(ImageData data : imageData) renderImage(data); }}Copy the code

5.2 Callable and Future tasks with results

Runnable as the basic task representation. Defect :1. No return value. 2. Do not throw a checked exception.

  • Callable interface

It is a better abstraction of the task, describing the return values and exceptions of a task.

    public interface Callable<V> {
        V call() throws Exception;
    }
Copy the code
  • The Future interface

It represents the life cycle of a task and provides methods to determine whether a task has been completed or cancelled.

    public interface Future<V> {
        boolean cancel(boolean mayInterruptIfRunning);
        boolean isCancelled();
        boolean isDone();
        V get() throws Exception;
        V get(long timeout, TimeUnit unit);
    }
Copy the code

5.3 Example: Implementing a page renderer with a Future

Split the rendering process into two tasks, one is to render all the text and one is to download all the images.

The code is slightly.Copy the code

Render text and render images concurrently.

5.4 Limitations in parallelization of heterogeneous tasks

In the above example, the speed of rendering text is much faster than the speed of rendering images. The efficiency of the program is not much different from that of serial execution, and the code does become more complex.

Performance gains can be seen only when a large number of independent and homogeneous tasks can be processed concurrently.

5.5 CompletionService: Executor and BlockingQueue

Submit a set of tasks, simple.

    @Test
    public void test() throws Exception{
        ExecutorService executor = Executors.newFixedThreadPool(5);
        List<Future<String>> futures = new ArrayList();
        for (int i=0; i<5; i++){
            final int param = i;
            Future<String> future = executor.submit(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    Thread.sleep(param * 1000);
                    return "result"+ param; }}); futures.add(future); }for(int i=4; i>0; i--) { System.out.println(futures.get(i).get()); }}Copy the code

CompletionService combines the functions of Executor and BlockingQueue. You can submit a Callable task to it for execution, and then use the take and poll methods similar to queue operations to get the finished result.

5.6 Example: Implementing a page renderer using CompletionService

Example in the book: omitted.

    @Test
    public void test() throws Exception{
        ExecutorService executor = Executors.newFixedThreadPool(5);
        CompletionService<String> completionService = new ExecutorCompletionService<>(executor);
        for (int i=4; i>0; i--){
            final int param = i;
            completionService.submit(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    Thread.sleep(param * 1000);
                    return "result"+ param; }}); }for(int i=0; i<4; i++) { System.out.println(completionService.take().get()); }} Output: result1 result2 result3 result4Copy the code

5.7 Setting time Limits for Tasks

Set the time for a single task.

    @Test
    public void singleTaskTest(){
        ExecutorService executor = Executors.newFixedThreadPool(5);
        Future<String> future = executor.submit(new Callable<String>() {
            @Override
            public String call() {
                try {
                    Thread.sleep(2000L);
                }catch (Exception e){
                    e.printStackTrace();
                }
                System.out.println("Mission accomplished...");
                return "singleTask."; }}); try { System.out.println(future.get(1, TimeUnit.SECONDS)); }catch (TimeoutException e){ System.out.println("Task timed out...");
            future.cancel(true); // This sentence does not affect the operation, the principle is unknown. }catch (InterruptedException e){ e.printStackTrace(); }catch (ExecutionException e){ e.printStackTrace(); }}Copy the code

5.8 Example: Luhang Reservation Portal

Do not set the timeout period for multiple tasks.

6. Summary

This chapter introduces the advantages and common requirements of the Java Executor framework. There is also the granularity of the task, analyzing the task boundaries according to the business scenario.