多线程框架:ForkJoin、Executors

ForkJoin简介

  • forkjoin框架是java7提供的用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇集每一个小任务结果得到大任务结果的框架。

核心思想:分治

  • fork:分解任务
  • join:收集数据在这里插入图片描述

代码示例

package com.fixData.util.use;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

//forkJoin框架
public class ForkJoinTest {

	// 需要处理的数据 
	// 根据业务需要,这里的String可以是Map、Json等等的任意实体
	private List<String> dataList;
	// 线程数,一般我用5个
	private int threadNum=5;

	public static void main(String[] args) {
		new ForkJoinTest().dowork();
	}

	private void dowork() {
		while (true) {
			// 通过查询 获得 需要处理的数据
			dataList = new ArrayList<String>();
			if (dataList == null || dataList.size() < 0) {
				System.out.println("dataList长度为0!!!");
				break;
			}
			// 通过forkjoin框架处理
			ForkJoinPool pool = new ForkJoinPool(100);
			Task task = new Task(dataList);// 传入需要处理的数据
			pool.submit(task);// 提交处理
			task.join();// 搜集数据
			//读取mysql、mongo数据,处理成功之后一般修改mysql数据状态
			//一般在mysql表中加status字段,0未处理,1处理成功,2处理失败等等
			//查询的时候直接查状态为0的数据
		}
	}

	// 处理数据
	private void deal(List<String> list) {
		for (String str : list) {

		}
	}

	// 直接用,除了类名什么都不用改
	class Task extends RecursiveTask<String> {
		// 根据线程将数据划分
		private int size = dataList.size() / threadNum == 0 ? 1 : dataList.size() / threadNum;
		private List<String> data;

		public Task(List<String> data) {
			this.data = data;
		}

		@Override
		protected String compute() {
			if (this.data.size() <= this.size) {
				System.out.println("********* size:" + data.size());
				deal(data);
			} else {
				// 细分成小任务
				List<Task> tasks = new ArrayList<ForkJoinTest.Task>();
				for (int index = 0; index * size < data.size(); index++) {
					Task task;
					if ((index + 1) * size > data.size()) {
						task = new Task(data.subList(index * size, data.size()));
					} else {
						task = new Task(data.subList(index * size, (index + 1) * size));
					}
					task.fork();
					tasks.add(task);
				}
				for (Task task : tasks) {
					task.join();
				}
			}
			return null;
		}

	}

}

本人工作用途:处理数据

  • 我一般用于读取mysql/mongo中的数据,通过多线程插入es中
  • 或者读取es数据,通过多线程插入mysql,或者导出到csv等等

类似于new Thread多线程

Thread thread1 = new Thread(new Runnable() {
	public void run() {
		try {
			//TODO something
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
});
Thread thread2 = new Thread(new Runnable() {
	public void run() {
		try {
			//TODO something
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
});

thread1.start();
thread2.start();
thread1.join();
thread2.join();//join 阻塞线程,等执行完毕再往下执行

System.out.println("执行完毕");

lambda表达式创建线程

new Thread(() -> System.out.println("Hello world !")).start();

Thread thread = new Thread(() -> System.out.println("Hello world !"));
		thread.start();
		thread.join();

=========================================
Executors框架

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import com.alibaba.controller.FileController;

//需要处理的数据集合
List<String> importCsv = CsvUtil.importCsv(new File(listPath));
		
		 
		int threadNum = 2;//线程数量
		ExecutorService pool = null;//线程池
		try {
			pool = Executors.newFixedThreadPool(threadNum);
			BlockingQueue<Future<Map<String, Map<String, Object>>>> queue = new LinkedBlockingQueue<Future<Map<String, Map<String, Object>>>>();
			ExecutorCompletionService<Map<String, Map<String, Object>>> completionService = new ExecutorCompletionService<Map<String, Map<String, Object>>>(
					pool, queue);
			for (String s : importCsv) {
				
				completionService.submit(() -> {
					try {
						Boolean batchUpload = new FileController().BatchUpload(s, "sifa");
						CsvUtil.appendUTF8Csv(logPath, s + "," + batchUpload + " \n");
					} catch (Exception e) {
						e.printStackTrace();
						CsvUtil.appendUTF8Csv(logPath, s + ",error \n");
					}
					return null;
				});
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (pool != null)
				pool.shutdown();
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值