異步線程池的使用

合理使用異步線程開發項目能提升一個項目的併發量,減小響應時間。下面就簡單介紹一下異步線程池的使用,參考博客:https://blog.csdn.net/hry2015/article/details/67640534java

spring 對@Async定義異步任務的方法有3種:spring

1.最簡單的異步調用,返回值爲void;併發

2.帶參數的異步調用,異步方法能夠傳入參數;異步

3.異常調用返回Futureasync

代碼以下:ide

package com.hry.spring.async.annotation;

import java.util.concurrent.Future;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;

/**
 * 異步方法調用
 * 
 * @author hry
 *
 */
@Component
public class AsyncDemo {
	private static final Logger log = LoggerFactory.getLogger(AsyncDemo.class);

	/**
	 * 最簡單的異步調用,返回值爲void
	 */
	@Async
	public void asyncInvokeSimplest() {
		log.info("asyncSimplest");
	}

	/**
	 * 帶參數的異步調用 異步方法能夠傳入參數
	 * 
	 * @param s
	 */
	@Async
	public void asyncInvokeWithParameter(String s) {
		log.info("asyncInvokeWithParameter, parementer={}", s);
	}

	/**
	 * 異常調用返回Future
	 * 
	 * @param i
	 * @return
	 */
	@Async
	public Future<String> asyncInvokeReturnFuture(int i) {
		log.info("asyncInvokeReturnFuture, parementer={}", i);
		Future<String> future;
		try {
			Thread.sleep(1000 * 1);
			future = new AsyncResult<String>("success:" + i);
		} catch (InterruptedException e) {
			future = new AsyncResult<String>("error");
		}
		return future;
	}

}

  

spring啓動配置的方式有兩種:測試

1.註解;spa

2.XML配置文件.net

咱們先說註解的方式:線程

@EnableAsync註解能夠開啓異步調用功能, public AsyncTaskExecutor taskExecutor() 方法自定義本身的線程池,線程池前綴」Anno-Executor」。若是不定義,則使用系統默認的線程池。代碼以下:

package com.hry.spring.async.annotation;

import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

/**
 * 經過@EnableAsync啓動異步方法
 * @author hry
 * 
 */
@SpringBootApplication
@EnableAsync // 啓動異步調用
public class AsyncApplicationWithAnnotation {
	private static final Logger log = LoggerFactory.getLogger(AsyncApplicationWithAnnotation.class);
	
	/**
	 * 自定義異步線程池
	 * 	若是沒有這個方法,則使用默認的線程池
	 * @return
	 */
    @Bean
    public AsyncTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setThreadNamePrefix("Anno-Executor");//設置線程名稱的前綴
        executor.setCorePoolSize(5);//設置核心線程數
        executor.setMaxPoolSize(10);//設置最大線程數

        // 設置拒絕策略
        executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
			@Override
			public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
				// .....
			}
		});
        // 使用預約義的異常處理類
        // executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        return executor;
    }
    
	public static void main(String[] args) {
		log.info("Start AsyncApplication.. ");
		SpringApplication.run(AsyncApplicationWithAnnotation.class, args);
	}
}

 如今寫測試類:

package com.hry.spring.async.annotation;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.hry.spring.async.annotation.AsyncApplicationWithAnnotation;
import com.hry.spring.async.annotation.AsyncDemo;

@RunWith(SpringRunner.class)
@SpringBootTest(classes=AsyncApplicationWithAnnotation.class)
public class AsyncApplicationWithAnnotationTests {
	@Autowired
	private AsyncDemo asyncDemo;
	
	@Test
	public void contextLoads() throws InterruptedException, ExecutionException {
		asyncDemo.asyncInvokeSimplest();
		asyncDemo.asyncInvokeWithParameter("test");
		Future<String> future = asyncDemo.asyncInvokeReturnFuture(1000);
		System.out.println(future.get());
	}
}

 啓動測試類,結果以下:

說明啓動異步線程池成功,執行上面的3個方法分別用了3個線程。

再說一下XML配置文件配置的方式:

咱們先建立XML配置文件:

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:task="http://www.springframework.org/schema/task"  
    xsi:schemaLocation="  
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
        http://www.springframework.org/schema/context   
http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd  
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"  
    default-lazy-init="false">  
    
  	<!-- 等價於 @EnableAsync, executor指定線程池 -->
  	<task:annotation-driven executor="xmlExecutor"/>
  	<!-- id指定線程池產生線程名稱的前綴 -->
    <task:executor
        id="xmlExecutor"
        pool-size="3-20"
        queue-capacity="100"
	    keep-alive="120"
        rejection-policy="CALLER_RUNS"/>
	
</beans>

  

其中id表示線程名稱的前綴,pool-size表示線程池的大小,「3-20」表示線程池的最大線程數爲20,最小線程數爲3,也能夠設置成一個值,如:pool-size=5,則表示線程池的核心線程數和最大線程數相同,都是5。queue-capacity表示排隊隊列的長度。

項目啓動時讀取xml配置文件,以下:

package com.hry.spring.async.xml;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;


/**
 * 經過XML啓動異步
 * @author hry
 *
 */
@SpringBootApplication
@ImportResource("classpath:/async/spring_async.xml")
public class AsyncApplicationWithXML {
	private static final Logger log = LoggerFactory.getLogger(AsyncApplicationWithXML.class);
	
	public static void main(String[] args) {
		log.info("Start AsyncApplication.. ");
		SpringApplication.run(AsyncApplicationWithXML.class, args);
	}
}  

 

編寫測試類:

package com.hry.spring.async.xml;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
 
@RunWith(SpringRunner.class)
@SpringBootTest(classes=AsyncApplicationWithXML.class)
public class AsyncApplicationWithXMLTest {
	@Autowired
	private AsyncDemo asyncDemo;

	@Test
	public void contextLoads() throws InterruptedException, ExecutionException {
		asyncDemo.asyncInvokeSimplest();
		asyncDemo.asyncInvokeWithParameter("test");
		Future<String> future = asyncDemo.asyncInvokeReturnFuture(100);
		System.out.println(future.get());
	}
}

  

測試結果以下:

測試成功。

相關文章
相關標籤/搜索