Java uses Executor and Fork-join framework concurrent programming

Executor

Executor is used when the number of tasks is known, and the number of tasks is submitted to the thread pool, and the thread pool allocates management threads by itself.
Insert picture description here
Insert picture description here
Note: Callable and Runnable are equivalent, but the run method of Runnable has no return value, while the call method of Callable can have a return value.
Example:

  1. SumTask class
import java.util.Random;
import java.util.concurrent.Callable;

//任务实现Callable接口
public class SumTask implements Callable<Integer> {
    
    
	//定义每个线程计算的区间
	private int startNumber;
	private int endNumber;
	
	public SumTask(int startNumber, int endNumber){
    
    
		this.startNumber=startNumber;
		this.endNumber=endNumber;
	}
	
	@Override
	public Integer call() throws Exception {
    
    
		int sum = 0;
		for(int i=startNumber; i<=endNumber; i++)
		{
    
    
			sum = sum + i;
		}
		
		Thread.sleep(new Random().nextInt(1000));
		
		System.out.printf("%s: %d\n",Thread.currentThread().getName(),sum);
		return sum;//返回局部总和
	}
}

  1. SumTest
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;


public class SumTest {
    
    

	public static void main(String[] args) {
    
    
		
		//执行线程池,线程的个数一般为cpu的两倍左右,不能太多ִ
		ThreadPoolExecutor executor=(ThreadPoolExecutor)Executors.newFixedThreadPool(4);
		
		List<Future<Integer>> resultList=new ArrayList<>();

		//统计1-1000总和,分成十个任务提交
		for (int i=0; i<10; i++){
    
    
			SumTask calculator=new SumTask(i*100+1, (i+1)*100);
			Future<Integer> result=executor.submit(calculator);//通过Future能获取线程返回值
			resultList.add(result);
		}
		
		//每隔50ms,轮询等待10个任务结束
		do {
    
    
			System.out.printf("Main:已经完成多少个任务:%d\n",executor.getCompletedTaskCount());
			for (int i=0; i<resultList.size(); i++) {
    
    
				Future<Integer> result=resultList.get(i);
				System.out.printf("Main: Task %d: %s\n",i,result.isDone());//获取当前任务是否完成
			}
			try {
    
    
				Thread.sleep(50);
			} catch (InterruptedException e) {
    
    
				e.printStackTrace();
			}
		} while (executor.getCompletedTaskCount()<resultList.size());
		
		// 所有任务都结束	
		int total = 0;
		for (int i=0; i<resultList.size(); i++) {
    
    
			Future<Integer> result=resultList.get(i);
			Integer sum=null;
			try {
    
    
				sum=result.get();//调用get()方法获取函数返回值
				total = total + sum;
			} catch (InterruptedException e) {
    
    
				e.printStackTrace();
			} catch (ExecutionException e) {
    
    
				e.printStackTrace();
			}
		}
		System.out.printf("1-1000总和:" + total);
		
		// 关闭线程池
		executor.shutdown();
	}
}

to sum up:

  1. ThreadPoolExecutor executor=(ThreadPoolExecutor)Executors.newFixedThreadPool(4);Create thread pool
  2. executor.submit(Task);Submit tasks to the thread pool
  3. executor.getCompletedTaskCount();Get the number of completed tasks
  4. Future.isdone();Get whether the current task is completed through Future
  5. Future.get();Get task return value through Future
  6. executor.shutdown();Close thread pool
  7. executor.getPoolSize();Get thread pool size

Fork-join

Divide and conquer programming is suitable for occasions where the amount of tasks is difficult to determine .
Insert picture description here
Example:

  1. SumTask
import java.math.BigInteger;
import java.util.concurrent.RecursiveTask;

//分任务求和extends RecursiveTask<Long>
public class SumTask extends RecursiveTask<Long> {
    
    
	
	private int start;
	private int end;

	public SumTask(int start, int end) {
    
    
		this.start = start;
		this.end = end;
	}

	public static final int threadhold = 5;//阈值

	@Override
	protected Long compute() {
    
    
		Long sum = 0L;
		
		// 如果任务足够小就直接执行
		boolean canCompute = (end - start) <= threadhold;
		if (canCompute) {
    
    
			for (int i = start; i <= end; i++) {
    
    
				sum = sum + i;				
			}
		} else {
    
    
			// 任务大于阈值,分裂为2个任务
			int middle = (start + end) / 2;
			SumTask subTask1 = new SumTask(start, middle);
			SumTask subTask2 = new SumTask(middle + 1, end);

			invokeAll(subTask1, subTask2);

			Long sum1 = subTask1.join();
			Long sum2 = subTask2.join();

			// 结果合并
			sum = sum1 + sum2;
		}
		return sum;
	}
}
  1. SumTest
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;

//分任务求和
public class SumTest {
    
    
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
    
        //创建执行线程池
    	ForkJoinPool pool = new ForkJoinPool();
    	//ForkJoinPool pool = new ForkJoinPool(4);
    	
    	//创建任务
        SumTask task = new SumTask(1, 10000000);
        
        //提交任务
        ForkJoinTask<Long> result = pool.submit(task);
        
        //等待结果
        do {
    
    
			System.out.printf("Main: Thread Count: %d\n",pool.getActiveThreadCount());
			System.out.printf("Main: Paralelism: %d\n",pool.getParallelism());
			try {
    
    
				Thread.sleep(50);
			} catch (InterruptedException e) {
    
    
				e.printStackTrace();
			}
		} while (!task.isDone());
        
        //输出结果
        System.out.println(result.get().toString());
    }
}

to sum up:

  1. ForkJoinPool pool = new ForkJoinPool();Create an execution thread pool
  2. SumTask task = new SumTask(1, 10000000);Create task
  3. ForkJoinTask<Long> result = pool.submit(task);Submit task
  4. result.get()Obtain the calculation result, that is, the return value of the rewritten compute function
  5. task.isDone()Whether the inspection task is completed
  6. pool.getActiveThreadCount()Get the number of threads in the entire thread pool
  7. pool.getParallelism()Get the degree of parallelism in the thread pool (how many threads are working at the same time

Use of data structures

Insert picture description here
Therefore, there needs to be some data structures suitable for concurrency:
Insert picture description here
Insert picture description here
Insert picture description here

Guess you like

Origin blog.csdn.net/DwenKing/article/details/109371149