高并发项目应用场景多线程性能优化

串行模式(123顺序执行,效率低下)

高并发项目应用场景多线程性能优化_第1张图片

controller

@Controller
public class UserController {
	private UserService userService;
	@RequestMapping("/info")
	public Object getInfo(@RequestParam("userId")long userId) {
		return userService.getUserInfo(userId);
	}
}

service

@Service
public class UserService {
	@Autowired
	private RemoteService remoteService;
	public Object getUserInfo(long userId) {
		long currentTimeMillis = System.currentTimeMillis();
		
		String V1 = remoteService.get001Info(userId);
		JSONObject parseObject1 = JSONObject.parseObject(V1);
		
		String V2 = remoteService.get002Info(userId);
		JSONObject parseObject2 = JSONObject.parseObject(V2);
		
		JSONObject jsonObject = new JSONObject();
		jsonObject.putAll(parseObject1);
		jsonObject.putAll(parseObject2);
		
		System.out.println("串行time"+(System.currentTimeMillis()-currentTimeMillis));
		return jsonObject;
	}
}

service并行模式(稍微提升,非最优解)

高并发项目应用场景多线程性能优化_第2张图片

不采用Runnable,它的Run方法没有返回值
采用Callable,它的call方法有返回值
通过.get方法获取返回值时如果线程没有走完,就会阻塞,阻塞的线程是web服务器的tomcat线程,大量线程阻塞,会导致网站吞吐量下降。
高并发项目应用场景多线程性能优化_第3张图片

@Service
public class UserService {
	@Autowired
	private RemoteService remoteService;
	public Object getUserInfoConcurrent( final long userId) {
		/// 
//		Thread thread = new Thread(new Runnable() {
//			public void run() {
//				
//			}
//		}).start();
		
		long currentTimeMillis = System.currentTimeMillis();
		/业务1
		Callable userCall=new Callable() {
			public JSONObject call() throws Exception {
				String V1 = remoteService.get001Info(userId);
				JSONObject parseObject1 = JSONObject.parseObject(V1);
				return parseObject1;
			}
		};
		FutureTask userFuture = new FutureTask(userCall);
		new Thread(userFuture).start();
		/业务2
		Callable moneyCall=new Callable() {
			public JSONObject call() throws Exception {
				String V2 = remoteService.get002Info(userId);
				JSONObject parseObject2 = JSONObject.parseObject(V2);
				return parseObject2;
			}
		};
		FutureTask moneyFuture = new FutureTask(moneyCall);
		new Thread(moneyFuture).start();
		///------------------------------------------
		JSONObject jsonObject = new JSONObject();;
		try {
			jsonObject.putAll(userFuture.get());//获取返回值时如果线程没有走完,就会阻塞,阻塞的线程是web服务器的tomcat线程,大量线程阻塞,会导致网站吞吐量下降。
			jsonObject.putAll(moneyFuture.get());
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("串行time"+(System.currentTimeMillis()-currentTimeMillis));
		return jsonObject;
	}
}

servlet3.0异步请求解决Tomcat线程阻塞

在controller层启动子线程(通过异步方式)
request过来,tomcat会启动一个子线程,然后自身结束,使得tomcat主线程的开闭许仙接近于0。
高并发项目应用场景多线程性能优化_第4张图片controller

@Controller
public class UserController {
	private UserService userService;
	@RequestMapping("/infoAsync")
	public Callable getUserInfoAsync(@RequestParam("userId") final long userId){
		final long TomcatStart = System.currentTimeMillis();
		//开启一个子线程
		Callable callable=new Callable() {
			public Object call() throws Exception {
				long childStart = System.currentTimeMillis();
				Object result=userService.getUserInfoConcurrent(userId);
				System.out.println("Child Thread("+Thread.currentThread()+")cost"+(System.currentTimeMillis()-childStart));
				return result;
			}
		};
		System.out.println("Tomcat Thread("+Thread.currentThread()+")cost"+(System.currentTimeMillis()-TomcatStart));
		return callable;
	}
}
 
  

批量调用降低后端服务器接口的调用频次(初步最优解)

1.将所有请求进一步封装,为每一个请求加上对应的序列号
2.创建一个阻塞队列,保护线程安全
3.创建一个定时器,随着项目启动初始化
4.在定时器中设定时间获取批量请求,得到相应之后,通过之前添加的序列号进行一一对应,然后返回。
高并发项目应用场景多线程性能优化_第5张图片
service

//将请求按照要求整理,加上对应编号
	class Request{
		String serialNo;
		String orderId;
		CompletableFuture> future;
	}
	//队列(阻塞队列,线程安全\性能考虑)
	LinkedBlockingDeque queue= new LinkedBlockingDeque<>();
	//项目启动时,初始化定时器
	@PostConstruct
	public void doBusiness() {
		//定时线程池,每隔10ms运行一次
		//线程池中要保留的线程数,一搬填1
		ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(1);
		//第一个参数,执行的任务    第二个参数是,第一次执行执行多少秒   第三个参数是,每多少秒执行一次  最后一个参数是单位
		threadPool.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				int size = queue.size();
				if(size==0) {
					return;
				}
				ArrayList> params = new ArrayList<>();
				ArrayList requests = new ArrayList<>();
				for(int i=0;i map = new HashMap<>();
					map.put("serialNo", request.serialNo);
					map.put("orderId", request.orderId);
					params.add(map);
					requests.add(request);
				}
				System.out.println("批量处理的数据量:"+size);
				List> response = remoteService.queryorderInfoByIdBatch(params);
				for(Request request:requests) {
					String serialNo=request.serialNo;
					for(Map res:response) {
						if(serialNo.equals(res.get("serialNo").toString())) {
							request.future.complete(res);
							break;
						}
					}
				}
			}
		}, 100, 10, TimeUnit.MILLISECONDS);
	}
	
	public Map queryorderBatch(String orderId) throws Exception{
		String serialNo = UUID.randomUUID().toString(); 
		CompletableFuture> future = new CompletableFuture<>();
		Request request = new Request();
		request.serialNo=serialNo;
		request.future=future;
		request.orderId=orderId;
		queue.add(request);
		return future.get();
	}

你可能感兴趣的:(java,性能优化,多线程并发)