線程執行器

這套機制分離了任務的建立和執行。經過使用執行器,僅僅須要實現Runnable接口的對象,而後將這些對象發送給執行器便可。執行器經過建立所需線程,來負責這些Runnable對象的建立,實例化以及運行。可是執行器的功能不限於此,他使用了線程池來提升應用程序的性能。當發送一個任務給執行器時,執行器會嘗試使用線程池中的線程來執行這個任務,避免了不斷地建立和銷燬線程而致使的性能降低。java

  • 建立線程執行器web

使用執行器框架(Executor Framework)第一步是建立ThreadPoolExecutor對象。能夠ThreadPoolExecutor類提供的四個構造器或者使用Executors的工廠類來建立ThreadPoolExecutor對象。
緩存

package com.packtpub.java7.concurrency.chapter4.recipe1.task;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * This class implements a concurrent task 
 *
 */
public class Task implements Runnable {

    /**
     * The start date of the task
     */
    private Date initDate;
    /**
     * The name of the task
     */
    private String name;
    
    /**
     * Constructor of the class. Initializes the name of the task
     * @param name name asigned to the task
     */
    public Task(String name){
        initDate=new Date();
        this.name=name;
    }
    
    /**
     * This method implements the execution of the task. Waits a random period of time and finish
     */
    @Override
    public void run() {
        System.out.printf("%s: Task %s: Created on: %s\n",Thread.currentThread().getName(),name,initDate);
        System.out.printf("%s: Task %s: Started on: %s\n",Thread.currentThread().getName(),name,new Date());
        
        try {
            Long duration=(long)(Math.random()*10);
            System.out.printf("%s: Task %s: Doing a task during %d seconds\n",Thread.currentThread().getName(),name,duration);
            TimeUnit.SECONDS.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.printf("%s: Task %s: Finished on: %s\n",Thread.currentThread().getName(),name,new Date());
    }

}
package com.packtpub.java7.concurrency.chapter4.recipe1.task;

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * This class simulates a server, for example, a web server, that receives
 * requests and uses a ThreadPoolExecutor to execute those requests
 *
 */
public class Server {
    
    /**
     * ThreadPoolExecutors to manage the execution of the request
     */
    private ThreadPoolExecutor executor;
    
    /**
     * Constructor of the class. Creates the executor object
     */
    public Server(){
        executor=(ThreadPoolExecutor)Executors.newCachedThreadPool();
    }
    
    /**
     * This method is called when a request to the server is made. The 
     * server uses the executor to execute the request that it receives
     * @param task The request made to the server
     */
    public void executeTask(Task task){
        System.out.printf("Server: A new task has arrived\n");
        executor.execute(task);
        System.out.printf("Server: Pool Size: %d\n",executor.getPoolSize());
        System.out.printf("Server: Active Count: %d\n",executor.getActiveCount());
        System.out.printf("Server: Completed Tasks: %d\n",executor.getCompletedTaskCount());
    }

    /**
     * This method shuts down the executor
     */
    public void endServer() {
        executor.shutdown();
    }

}
package com.packtpub.java7.concurrency.chapter4.recipe1.core;

import com.packtpub.java7.concurrency.chapter4.recipe1.task.Server;
import com.packtpub.java7.concurrency.chapter4.recipe1.task.Task;

/**
 * Main class of the example. Creates a server and 100 request of the Task class
 * that sends to the server
 *
 */
public class Main {

    /**
     * Main method of the example
     * @param args
     */
    public static void main(String[] args) {
        // Create the server
        Server server=new Server();
        
        // Send 100 request to the server and finish
        for (int i=0; i<100; i++){
            Task task=new Task("Task "+i);
            server.executeTask(task);
        }
        
        server.endServer();

    }

}

若是須要執行新的任務,緩存線程池就會建立新線程;若是線程所運行的任務執行完成後而且這個線程可用,那麼緩存線程池將會重用這些線程。線程的重用的優勢是減小了建立新線程所花費的時間。然而,新任務固定會依賴線程來執行,所以緩存線程池也有缺點,若是發送過多的任務給執行器,系統的負荷將會過載。框架

PS:僅當線程的數量是合理的或者線程只會運行很短的時間,合適採用Executors工廠類的newCachedThreadPool()方法來建立執行器。dom

ThreadPoolExecutor類的重要特性是,一般須要顯示地去結束他。
ide

相關文章
相關標籤/搜索