SpringBoot創建同步及異步線程池並定時記錄線程池運行狀態

一 線程池


二通用線程池

廢話沒有,見代碼
MyThreadInfo :記錄線程運行信息


import javax.persistence.Entity;
import lombok.Data;

@Entity(name="t_thread_info")
@Data
public class MyThreadInfo {
	//存活數量
	private int activeCount;
	//最大數量
	private int maxPoolSize;
	//當前線程池大小
	private int poolSize;
	//線程池基本大小
	private int corePoolSize;
	//隊列長度
	private int queue_size;
	//可用隊列長度
	private int avali_queue_size;
	//線程組名字
	private String threadGroupName;
	//服務器地址
	private String hostAddress;
	
}

ThreadPoolUtils 創建同步及異步線程池


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

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.google.common.util.concurrent.ListeningExecutorService;

import com.google.common.util.concurrent.MoreExecutors;

@Configuration
public class ThreadPoolUtils {

    /**
     * 線程池維護線程的最少數量
     */
    private int corePoolSize = 10;                                                                       

    /**
     * 線程池維護線程的最大數量
     */
    private int maxPoolSize = 50;

    /**
     * 緩存隊列
     */
    private int queueCapacity = 100;

    /**
     * 允許的空閒時間
     */
    private int keepAlive = 60;

    //同步線程池
    @Bean(name = "syncExceutor")
    public ThreadPoolTaskExecutor syncExceutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setKeepAliveSeconds(keepAlive);
        executor.setQueueCapacity(queueCapacity);
        executor.setThreadNamePrefix("mqExecutor-");
         // rejection-policy:當pool已經達到max size的時候,如何處理新任務
        // CALLER_RUNS:不在新線程中執行任務,而是由調用者所在的線程來執行
        //對拒絕task的處理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

    //異步線程池
    @Bean(name = "asyncExceutor")
    public AsyncTaskExecutor asyncExceutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setKeepAliveSeconds(keepAlive);
        executor.setQueueCapacity(queueCapacity);
        executor.setThreadNamePrefix("mqExecutor-");
         // rejection-policy:當pool已經達到max size的時候,如何處理新任務
        // CALLER_RUNS:不在新線程中執行任務,而是由調用者所在的線程來執行
        //對拒絕task的處理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
    
    
}

TaskQuart 定時任務,定時查詢線程池運行狀態及數據


import java.net.InetAddress;
import java.util.concurrent.ThreadPoolExecutor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;

import eureka.manager.entity.MyThreadInfo;

@Component
public class TaskQuart {

	@Autowired
	private ThreadPoolTaskExecutor syncExceutor;
	
	@Autowired
	private AsyncTaskExecutor asyncExceutor;
	
	@Scheduled(cron = "0/5 * * * * *")
	public void getThreadInfo(){
		InetAddress inte = null;
		try{
			inte = InetAddress.getLocalHost();
		}catch(Exception e){
			e.printStackTrace();
		}
		Object [] myThread = {syncExceutor,asyncExceutor};
		for(Object thread : myThread){
			MyThreadInfo info = new MyThreadInfo();
			ThreadPoolTaskExecutor threadTask = (ThreadPoolTaskExecutor)thread;
			//存活數量
			info.setActiveCount(threadTask.getActiveCount());
			//線程池基本大小
			info.setCorePoolSize(threadTask.getCorePoolSize());
			//最大數量
			info.setMaxPoolSize(threadTask.getMaxPoolSize());
			//當前線程池大小
			info.setPoolSize(threadTask.getPoolSize());
			
			//線程組名字
			ThreadGroup threadGroup = threadTask.getThreadGroup();
			info.setThreadGroupName(threadGroup.getName());
			
			ThreadPoolExecutor threadPoolExecutor = threadTask.getThreadPoolExecutor();
			//可用隊列長度
			info.setAvali_queue_size(threadPoolExecutor.getQueue().remainingCapacity());
			//隊列長度
			info.setQueue_size(threadPoolExecutor.getQueue().size());
			//服務器地址
			info.setHostAddress(inte.getHostAddress());
			
			System.out.println(JSONObject.toJSONString(info));
			
		}
	}
}

實現Runnable接口和Callable接口的區別

如果想讓線程池執行任務的話需要實現的Runnable接口或Callable接口。

Runnable接口或Callable接口實現類都可以被ThreadPoolExecutor或ScheduledThreadPoolExecutor執行。

兩者的區別在於 Runnable 接口不會返回結果但是 Callable 接口可以返回結果。

執行execute()方法和submit()方法的區別

1)execute() 方法用於提交不需要返回值的任務,所以無法判斷任務是否被線程池執行成功與否;

2)submit() 方法用於提交需要返回值的任務。線程池會返回一個Future類型的對象,通過這個Future對象可以判斷任務是否執行成功,並且可以通過future的get()方法來獲取返回值,get()方法會阻塞當前線程直到任務完成,而使用 get(long timeout,TimeUnit unit)方法則會阻塞當前線程一段時間後立即返回,這時候有可能任務沒有執行完。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章