欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

多线程使用解决并带主动超时的问题

程序员文章站 2024-01-13 19:39:46
...

项目中有时我们需要更新很多记录的不同信息,因为数量多,操作耗时不确定,时长时短,还有可能操作到半卡住,既不断开也没返回结果,有可能等待数天的情况,这肯定不是我们希望的,所以在设计时我们希望,任务列表执行时,能主动控制方法执行的超时时间,如果超时了或有异常就抛出异常,同时每次触发进行具体的业务操作又是一连串完整的业务流程操作;串行处理是可以完成,但可能等待的时间比较长,所以设法有多路并行触发业务方法,同时又能控制主动超时,这样是最快的;于是设计思路如下:

1,业务执行方法,一个真正执行一连串完整的业务流程操作,无返回或返回的结果可以不理,执行业务方法的时间不确定,有长有短或一直连着;如:realUpdateInfo();

2,一个能主动控制超时的方法,其设计目的就是要求在规定时间内执行真正业务方法,如果执行不完就触发超时,业务方法出现异常也抛出异常,主要是只管触发执行和控制超时;如:updateInfoWithTimeout()

3,业务任务方法,使用线程池中多个线程同时并行触发任务;如:updateAllProductInfo()

参考例子如下:

package com.qyh.pro01.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.springframework.transaction.annotation.Transactional;

import com.qyh.pro01.model.Product;

/**
 * @author shenzhenNBA
 *
 */
public class InfoUpdateServiceImpl {
	
	//单个线程池
	//private static ExecutorService executorService2 = Executors.newSingleThreadExecutor();
	
	//定义有100个线程的线程池
	private static ExecutorService executorService = Executors.newFixedThreadPool(100);
	
	
	/**
	 * 任务方法,使用线程池中100个线程同时并行触发任务
	 */
	public void updateAllProductInfo() {
		
		List<Product> allProduct = new ArrayList<Product>();
		//allProduct = prodcutDao.queryAll(); //假如数量巨大或更新比较费时
		long timeoutNumber = 30*1000; //30秒
		for (Product product : allProduct) {
			this.updateInfoWithTimeout(timeoutNumber,product);
		}
	}
	
	/**
	 * 带有主动超时的方法,如果是没必要等返回值的情况就不需要等待结果,只管触发执行,
	 * 其设计目的就是要求在规定时间内执行真正业务方法,如果执行不完就触发超时,业务方法出现异常也抛出异常
	 * @param timeoutNumber 仅对等待返回结果的有效
	 * @param productParam
	 * @return
	 */
	public String updateInfoWithTimeout(long timeoutNumber, Product productParam) {
        String result = "no";
        FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return realUpdateInfo(productParam);
            }
        });
	    try { 
        	//只管使用线程池里不同的线程触发真正的业务执行,使用线程池默认的超时时间处理超时
	    	//业务不需要等待结果,无返回或返回的结果可以不理的情况,
	    	executorService.execute(futureTask);
	    	result = "ok";
	    	
	    	//此处代码会等待返回结果,但如果超时还是触发超时,仅对必须等待返回结果才能进行后续操作
            //result = futureTask.get(timeoutNumber, TimeUnit.MILLISECONDS);
        //} catch (InterruptedException | ExecutionException | TimeoutException e) {
            //e.printStackTrace();
            //futureTask.cancel(true);
        } catch (Exception e) {
        	//log info show here...
            result = "timeoutOrException";
        }
        return result;
    }
	
	
	/**
	 * 实际含具体的业务逻辑工作的方法,
	 * @param productParam
	 * @return
	 */
	@Transactional
	public String realUpdateInfo(Product productParam) {
		
		//此处真正执行业务方法的时间不确定,
		//但却是一连串完整的业务流程操作,无返回或返回的结果可以不理
		//real buiz code go here...
		
		return null;
	}
	
	

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}

欢迎拍砖讨论...