Java基础知识七

并行模式


-主从模式(Master-Slave)
-Worker模式(Worker-Worker)
·Java并发编程
-Thread/Runnable/Thread组管理
-Executor(本节重点)
-Fork-Join框架

线程组ThreadGroup


-线程的集合
-树形结构,大线程组可以包括小线程组

-可以通过enumerate方法遍历组内的线程,执行操作

-能够有效管理多个线程,但是管理效率低

-任务分配和执行过程高度耦合
-重复创建线程、关闭线程操作,无法重用线程

package thread.threadgroup;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
        ThreadGroup threadGroup = new ThreadGroup("Searcher");

        Result result = new Result();
        //创建一个任务,10个线程完成
        Searcher searchTask = new Searcher(result);
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(threadGroup, searchTask);
            thread.start();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("++++++++++++++++++++++++++++++++++++");
        System.out.printf("active 线程数量:%d\n",threadGroup.activeCount());
        System.out.printf("线程组信息明细\n");
        threadGroup.list();
        System.out.println("===========================");
        //遍历线程组
        Thread[] threads=new Thread[threadGroup.activeCount()];
        threadGroup.enumerate(threads);
        for(int i=0;i<threadGroup.activeCount();i++){
            System.out.printf("Thread %s: %s\n",threads[i].getName(),threads[i].getState());
        }
        System.out.println("===========================");
        waitFinish(threadGroup);
        threadGroup.interrupt();
    }

    public static void waitFinish(ThreadGroup threadGroup){
        while (threadGroup.activeCount()>9){
            try {
                TimeUnit.SECONDS.sleep(1);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}
package thread.threadgroup;

import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class Searcher implements Runnable {
    private Result result;

    public Searcher(Result result){
        this.result=result;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.printf("Thread %s: 启动\n",name);
        try {
            doTask();
            result.setName(name);
        }catch (InterruptedException e){
            System.out.printf("Thread %s: 被中断\n",name);
        }
        System.out.printf("Thread %s: 完成\n",name);
    }

    private void doTask() throws InterruptedException{
        Random random = new Random((new Date()).getTime());
        int value = (int)(random.nextDouble()*100);
        System.out.printf("Thread %s: %d\n",Thread.currentThread().getName(),value);
        TimeUnit.SECONDS.sleep(value);
    }
}
package thread.threadgroup;

public class Result {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

activeCount,返回线程组中还处于active的线程数(估计数);enumerate,将线程组中active的线程拷贝到数组中;interrupt,对线程组中所有的线程发出interrupt信号;打印线程组中所有的线程信息

Executor框架

从JDK5开始提供Executor FrameWork (java.util.concurrent.*)

-分离任务的创建和执行者的创建

-线程重复利用(new线程代价很大)理解共享线程池的概念
-预设好的多个Thread,可弹性增加
多次执行很多很小的任务
任务创建和执行过程解耦一
程序员无需关心线程池执行任务过程

主要类:ExecutorService,ThreadPoolExecutor,Future-Executors.newCachedThreadPool/newFixedThreadPool 创建线程池

-ExecutorService 线程池服务
-Callable 具体的逻辑对象(线程类)
-Future 返回结果

public class Main {
    public static void main(String[] args) throws InterruptedException{

        Server server = new Server();
        for (int i=0;i<100;i++){
            Task task = new Task("Task "+i);
            Thread.sleep(10);
            server.submitTask(task);
        }
        server.endServer();
    }
}


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

public class Server {
    private ThreadPoolExecutor executor;
    public Server(){
        executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
        //executor = (ThreadPoolExecutor) Executor.newCachedThreadPool();
    }

    public void submitTask(Task task){
        System.out.printf("Server: A new task has arrived\n");
        executor.execute(task);
        System.out.printf("Server: Pool size: %d\n", executor.getPoolSize());
        System.out.printf("Server: Active Account: %d\n", executor.getActiveCount());
        System.out.printf("Server: Completed Tasks: %d\n", executor.getCompletedTaskCount());
    }

    public void endServer(){
        executor.shutdown();
    }
}
package org.example.executor;

import java.util.Date;

public class Task implements Runnable {
    private String name;

    public Task(String name){
        this.name=name;
    }

    public void run(){
        try {
            Long duration = (long) (Math.random()*1000);
           System.out.printf("%s: Task %s: Doing a task during %d seconds\n", Thread.currentThread().getName(),Thread.currentThread().getId(),duration);
            Thread.sleep(duration);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.printf("%s: Task %s: Finished on: %s\n", Thread.currentThread().getName(),Thread.currentThread().getId(),new Date().getTime());
    }
}

另一个例子

package org.example.executor;

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){
        
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(4);

        List<Future<Integer>> resultList =new ArrayList<>();

        for (int i = 0; i <10; i++) {
            SumTask calcuator = new SumTask(i*100+1,(i+1)*100);
            Future<Integer> result = executor.submit(calcuator);
            resultList.add(result);
        }

        //每隔50毫秒 轮询等待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();
                total = total+ sum;
            }catch (InterruptedException e){
                e.printStackTrace();
            }catch (ExecutionException e){
                e.printStackTrace();
            }
        }
        System.out.printf("1-1000 总和:"+ total);
        executor.shutdown();
    }
}
package org.example.executor;

import java.util.Random;
import java.util.concurrent.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;
    }
}

在Java中,Future 接口是java.util.concurrent包的一部分,它用于表示异步计算的结果。一个 Future 对象用于封装那些可能还没有完成的计算任务的结果。使用 Future,你可以启动一个计算任务,然后立即继续执行其他任务,而不是等待计算完成。当需要计算结果时,你可以通过 Future 对象来获取它,如果计算尚未完成,那么 Future 的 get 方法会阻塞当前线程直到计算完成。

Future 的主要方法

  • V get() throws InterruptedException, ExecutionException:等待计算完成,然后检索其结果。如果计算尚未完成,则此方法会阻塞当前线程直到它完成。
  • V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException:等待计算完成,直到给定的等待时间结束,然后检索其结果。
  • boolean isDone():如果计算完成,则返回 true
  • boolean isCancelled():如果计算被取消,则返回 true
  • boolean cancel(boolean mayInterruptIfRunning):尝试取消计算。如果计算正在运行,则根据 mayInterruptIfRunning 参数的值,可能会尝试停止计算。

在Java的java.util.concurrent包中,Callable接口与Runnable接口相似,但有一个关键的区别:Callable接口的call方法可以返回一个结果,并且可以抛出一个异常,而Runnable接口的run方法既没有返回值也不能抛出受检查的异常(只能抛出RuntimeExceptionError)。 

Fork-Join框架

提供另一种并行框架:分解、治理、合并(分治编程)

适合用于整体任务量不好确定的场合(最小任务可确定)

package org.example.executor1;

import java.util.concurrent.*;

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());
    }
}
package org.example.executor1;

import java.util.concurrent.RecursiveTask;

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
    public Long compute() {
        Long sum = 0L;
        boolean canCompute = (end - start) <= threadhold;

        if (canCompute) {
            for (int i = start; i <= end; i++) {
                sum = sum + i;
            }
        } else {
            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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

larance

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值