JAVA_多线程fork/join_实战

一.创建线程的3种方式

  1. 继承Thread类重写run方法,实际上实现了Runable接口
public class Main   {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new Thread() {
            @Override
            public void run() {
                for (int i = 0; i <100 ; i++) {
                    System.out.println("i="+i);
                }
            }
        }.start();
    }
}
  1. 定义实现Runnable接口的类并重写run方法
public class Main   {
    public static void main(String[] args) {

        new Thread(()->{
            for (int i = 0; i <100 ; i++) {
                System.out.println("i="+i);
            }
        });
    }
}
  1. 实现Callable接口创建futureTask(实现了Runnable)对象,通过get获得结果
public class Main   {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask=new FutureTask<>( ()->{
            int sum=0;
            for (int i = 0; i <100 ; i++) {
                sum+=i;
            }
            return sum;
        });
        new Thread(futureTask).start();
        System.out.println(futureTask.get());//获取futureTask结果
    }
}

二.线程的基本操作

  1. 线程的一些基本属性设置和获取
public class Main   {
    public static void main(String[] args){
        Thread.currentThread();//得到当前线程
        Thread.activeCount();//获得活跃的线程数量
        //Thread.State 顶一个线程各种状态常量
        Thread thread=new Thread();
        thread.getName();//获取线程名字
        thread.getId();//获取线程ID
        thread.setPriority(Thread.NORM_PRIORITY);
        //设置线程优先级,优先级高的获得cpu执行权概率越高,高优先级的需要定时的调用yield和slepp等方法,给其他第优先级线程机会。
        thread.setDaemon(true);//设置线程位守护线程,守护线程是为其他线程做辅助工作,不能单独运行,其他所有线程结束,他就结束
    }
}
  1. 线程的时间调度
  1. Theard.sleep(long time);
    ①sleep()释放CPU执行权,但不释放同步锁;
    ②wait()释放CPU执行权,也释放同步锁,使得其他线程可以使用同步控制块或者方法。
    这是两个的关键区别
public class Main   {
    public static void main(String[] args) throws InterruptedException {
        Thread.sleep(1000);//当前所在线程进入1000毫秒timeWatiing状态,时间结束后进入就绪状态

    }
}
  1. thread.join();
public class Main   {
    public static void main(String[] args) throws InterruptedException {
        Thread thread=new Thread(()->{
            for (int i = 0; i < 100; i++) {
                System.out.println("i="+i);
            }
        });
        Thread thread1=new Thread(()->{
            for (int i = 0; i < 100; i++) {
                if(i==2){
                    try {
                        thread.join(1);
                        //表示让thread先执行1毫秒,然后在一起竞争cpu执行权
                        //如果为0表示一直等待,直到结束,进入就绪
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("j="+i);
            }
        });
        thread.start();
        thread1.start();
    }
}
  1. thread.yield()
public class Main   {
    public static void main(String[] args) throws InterruptedException {
        Thread thread=new Thread(()->{
            for (int i = 0; i < 100; i++) {
                System.out.println("i="+i);
            }
        });
        Thread thread1=new Thread(()->{
            for (int i = 0; i < 100; i++) {
                if(i==2){
                        thread.yield();
                        //表示让步,thread线程直接进入就绪状态,在于其他线程共同竞争
                }
                System.out.println("j="+i);
            }
        });
        thread.start();
        thread1.start();
    }
}

  1. 线程的停止或中断
  1. 设置bool值进行循环判断
public class Main   {
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread=new MyThread();
        myThread.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("j="+i);
            if(i==5){

                myThread.stopFlag=true;
            }
        }
    }

}
class  MyThread extends  Thread{
    public boolean stopFlag;
    @Override
    public void run() {
        for (int i = 0; i <100 && !stopFlag; i++) {
            System.out.println("i="+i);
        }
    }
}
  1. 通过淘汰的thread.stop()

为什么会弃用呢:
为什么弃用stop:
调用 stop() 方法会立刻停止 run() 方法中剩余的全部工作,包括在 catch 或 finally 语句中的,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭。
调用 stop() 方法会立即释放该线程所持有的所有的锁,导致数据得不到同步,出现数据不一致的问题。
例如,存在一个对象 u 持有 ID 和 NAME 两个字段,假如写入线程在写对象的过程中,只完成了对 ID 的赋值,但没来得及为 NAME 赋值,就被 stop() 导致锁被释放,那么当读取线程得到锁之后再去读取对象 u 的 ID 和 Name 时,就会出现数据不一致的问题.

 thread.stop()
  1. 通过thread.interrupt()

这个方法不同于stop()他不是立即终止线程,而是在目标线程中打一个标记,通过这个标记,更具需要处理你的代码。注意下面的代码:

public boolean Thread.isInterrupted() //判断是否被中断,静态方法
public static boolean Thread.interrupted() //判断是否被中断,并清除当前中断状态实例方法
public class Main   {
    public static void main(String[] args) throws InterruptedException {
        Thread thread=new Thread(()->{
            for (int i = 0; i < 100; i++) {
                if(Thread.currentThread().isInterrupted()){
                    break;
                }
                System.out.println(i);
            }
            System.out.println(Thread.currentThread().isInterrupted());//不会清除中断标志
            System.out.println(Thread.currentThread().isInterrupted());
            System.out.println(Thread.currentThread().isInterrupted());
            System.out.println(Thread.currentThread().isInterrupted());
        });
        thread.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("j="+i);
            if(i==0){
                thread.interrupt();
            }
        }
    }
}

如果当前线程处于阻塞状态,比如sleep状态,当调用中断方法时会抛出异常,若希望中断发生就停止可以这么做
用try catch finally 包裹循环

public class Main   {
    public static void main(String[] args) throws InterruptedException {
        Thread thread=new Thread(()->{
            int i=0;
            try {
                while (true){
                    System.out.println(i++);
                    Thread.sleep(1000);
                }
            }
            catch (InterruptedException e){
                
            }
            finally {
                System.out.println("释放资源的代码");
            }
        });
        thread.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("j="+i);
            if(i==0){
                thread.interrupt();
            }
        }
    }
}

三.线程的案例–闪烁的文本利用javafx实现

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Main extends Application {
    public static void main(String[] args) {
        launch( args);
    }
    @Override
    public void start(Stage primaryStage) throws Exception {
        Text text=new Text("Welcome");
        new Thread(()->{
            while (true){
                if(text.getText().length()>0){
                    Platform.runLater(()->{
                        text.setText("");
                    });
                }
                else {
                    Platform.runLater(()->{//通知ui线程修改ui,子线程不能修改ui线程
                        text.setText("Welcome");
                    });
                }
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        StackPane stackPane=new StackPane(text);
        primaryStage.setScene(new Scene(stackPane));
        primaryStage.show();
    }
}

三.4种jdk内置的线程池(面试前要好好攻克补充难点)

1、降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

2、提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。

3、提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控.

CachedThreadPool适合多个轻量级任务,几乎可以创建无限个线程(整数最大值),如果超过60秒没有人用这个线程则会销毁这个资源,重复利用

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
    public static void main(String[] args) {
        Thread thread=null;
        ExecutorService threadPool= Executors.newCachedThreadPool();//创建线程池
        threadPool.execute(()->{//通过线程池中的线程运行任务
            for (int i = 0; i < 100; i++) {
                System.out.println(i);
            }
        });
    }
}

FixedThreadPool 固定大小的线程池,不会销毁,最好使用Runtime.getRuntime().availableProcessors()来获取系统可以并行的最大线程数,这样可以从分利用系统处理器

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
    public static void main(String[] args) {
        Thread thread=null;
        ExecutorService threadPool= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        //创建固定大小线程池,最好使用Runtime.getRuntime().availableProcessors()
        //来获取系统可以并行的最大线程数,这样可以从分利用系统处理器
        threadPool.execute(()->{//通过线程池中的线程运行任务
            for (int i = 0; i < 100; i++) {
                System.out.println(i);
            }
        });
    }
}

newScheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行。延迟执行示例代码如下:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
        Thread thread=null;
        ScheduledExecutorService threadPool= Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
        //创建固定大小线程池,最好使用Runtime.getRuntime().availableProcessors()来获取系统可以并行的最大线程数,这样可以从分利用系统处理器
        threadPool.schedule(()->{
            return 5;
        }, 3, TimeUnit.SECONDS);//3秒后执行有返回值的任务
        threadPool.scheduleAtFixedRate(()->{
            System.out.println(5);
        },3,2,TimeUnit.SECONDS);//按固定周期执行任务
    }
}

newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。示例代码如下:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) {
        Thread thread=null;
        ExecutorService threadPool= Executors.newSingleThreadExecutor();
        threadPool.execute(()->{
            System.out.println(5);
        });
    }
}

四.向现称此种提交任务

  1. execute没有返回值,无法判断线程是否执行成功
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) {
        Thread thread=null;
        ExecutorService threadPool= Executors.newSingleThreadExecutor();
        threadPool.execute(()->{
            System.out.println(5);
        });
    }
}
  1. submit返回一个future 通过future中的get获取返回值,会阻塞线程
    get(long timeout, TimeUnit unit)方法则会阻塞一段时间后立即返回,这时有可能任务没有执行完。
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Thread thread=null;
        ExecutorService threadPool= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        java.util.concurrent.Future<Integer> future= threadPool.submit(()->{
            int sum=0;
            for (int i = 0; i <100; i++) {
                sum+=i;
            }
            return sum;
        });
        System.out.println(future.get());
    }
}

五.关闭线程池

可以通过调用线程池的shutdown或shutdownNow方法来关闭线程池,原理是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以无法响应中断的任务可能永远无法终止。两者的区别是:shutdownNow首先将线程池的状态设置成STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表,而shutdown只是将线程池的状态设置成SHUTDOWN状态,然后中断所有没有正在执行任务的线程。

只要调用了这两个关闭方法的其中一个,isShutdown方法就会返回true。当所有的任务都已关闭后,才表示线程池关闭成功,这时调用isTerminaed方法会返回true。至于我们应该调用哪一种方法来关闭线程池,应该由提交到线程池的任务特性决定,通常调用shutdown来关闭线程池,如果任务不一定要执行完,则可以调用shutdownNow。

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Thread thread=null;
        ExecutorService threadPool= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        for (int i = 0; i < 1000; i++) {
            java.util.concurrent.Future<Integer> future= threadPool.submit(()->{
                int sum=0;
                for (int j = 0; j <100; j++) {
                    sum+=j;
                }
                return sum;
            });
        }
        threadPool.shutdownNow();
        System.out.println(threadPool.isShutdown());//只要调用了shut相关方法都会返回true
        System.out.println( threadPool.isTerminated());//只有当所有任务成功关闭,才返回true
    }
}

六.线程同步

  1. synchronized关键字

同步方法,如果时静态方法,这是锁住了这个类

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Acount acount=new Acount();
        ExecutorService executorService=Executors.newCachedThreadPool();
        for (int i = 0; i < 100; i++) {
            executorService.execute(()->{
                try {
                    acount.add(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executorService.shutdown();
        while (!executorService.isTerminated()){
        }
        System.out.println(acount.getBlance());
    }
}
class  Acount{
    private  int blance;

    public int getBlance() {
        return blance;
    }
    public  synchronized void add(int count) throws InterruptedException {//同步方法
        int newBlance=blance+count;
        Thread.sleep(50);
        blance=newBlance;
    }
}

同步代码块

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Acount acount=new Acount();
        ExecutorService executorService=Executors.newCachedThreadPool();
        for (int i = 0; i < 100; i++) {
            executorService.execute(()->{
                try {
                    acount.add(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executorService.shutdown();
        while (!executorService.isTerminated()){
        }
        System.out.println(acount.getBlance());
    }
}
class  Acount{
    private  int blance;

    public int getBlance() {
        return blance;
    }
    public   void add(int count) throws InterruptedException {//同步方法
        synchronized (this){
            int newBlance=blance+count;
            Thread.sleep(50);
            blance=newBlance;
        }

    }
}

显式锁(相互排斥的锁)Lock(抽象方法)
lock()得到一个锁
unlock()释放锁
newCondition()用此锁创建一个Condition实例,用作线程协作
ReentrantLock是Lock的一个实例
new ReentrantLock(boolen fair);为真则等待时间长的获取到锁概率高,但性能差点
new ReentrantLock()=new ReentrantLock(false)

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Acount acount=new Acount();
        ExecutorService executorService=Executors.newCachedThreadPool();
        for (int i = 0; i < 100; i++) {
            executorService.execute(()->{
                try {
                    acount.add(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executorService.shutdown();
        while (!executorService.isTerminated()){
        }
        System.out.println(acount.getBlance());
    }
}
class  Acount{
    private   int blance;
    private Lock lock=new ReentrantLock();
    public int getBlance() {
        return blance;
    }
    public   void add(int count) throws InterruptedException {//同步方法
        lock.lock();//获取到锁
        try {
            int newBlance=blance+count;
            Thread.sleep(0);
            blance=newBlance;
        }
        catch (InterruptedException e){

        }
        finally {
            lock.unlock();//写在finally种是一个好习惯
        }
    }
}

七.线程之间的通信(监视器和这个的对比,后面注意去看下)–通过生产者和消费者的例子

import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main {
    public static void main(String[] args)  {
        Producer producer=new Producer(new Storeger());
        ExecutorService executorService= Executors.newCachedThreadPool();
        executorService.execute(()->{
            try {
                producer.add();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        executorService.execute(()->{
            try {
                producer.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }
}
class   Producer{//生产者和消费者写在一起了
    private Storeger storeger;
    public  Producer(Storeger storeger){
        this.storeger=storeger;
    }
    public  void add() throws InterruptedException {
        while (true){
            storeger.add();
        }
    }
    public  void get() throws InterruptedException {
        while (true){
            storeger.get();
        }
    }
}
class Storeger{
    public  static final    int MAX_COUNT = 100;
    private LinkedList<Integer> list=new LinkedList<>();
    private Lock lock=new ReentrantLock();
    private Condition isAdd=lock.newCondition();
    private Condition isGet=lock.newCondition();
    public  void add(){
        lock.lock();
        try {

            if (list.size()==MAX_COUNT){
                isGet.await();//当仓库满了,我就要等待被获取的信号
            }
            System.out.println("添加10个数据 现在有"+list.size());
            for (int i = 0; i < 10; i++) {
                list.offerLast(i);

            }
            isAdd.signalAll();//每次添加了,就可以通知消费者进行消费了
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }
    public  void get(){
        lock.lock();
        try {
            if (list.size()==0){
                isAdd.await();
            }
            System.out.println("开始获得10个数据 现在有"+list.size());
            for (int i = 0; i < 10; i++) {
                list.pollLast();
            }
            isGet.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally
        {
            lock.unlock();
        }
    }
}

七.阻塞队列

阻塞队列能够在队列满的时候导致线程阻塞,必须另一个线程将他删除一个元素才能继续,
当空的 时候必须由另一个线程进行添加才能继续
put()添加到尾部,take()从头部删除元素
ArrayBlockingQueue 指定容量和公平策略,数组实现
LinkedBlockingQueue 如果不指定容量put()方法将不会阻塞
PriorityBlockingQueue 元素按优先级排序
还有其他的了解下

通过这些阻塞队列我们能够更方便实现生产者和消费者模式

八.信号量(了解下)–限定访问某个资源的线程数量

九.死锁

有两个或多个对象需要在共享对象上获取锁,就会造成死锁

class Producer{
    Lock lock=new ReentrantLock();
    Lock lock1=new ReentrantLock();
    public  void add(){
        lock.lock();
        lock1.lock();
        try {

        }
        finally {
            lock1.unlock();
            lock.unlock();
        }
    }
    public  void get(){
        lock1.lock();
        lock.lock();
        try {

        }
        finally {
            lock.unlock();
            lock1.unlock();
        }
    }
}

避免死锁的机制
就是获取锁的顺序一致,资源排序

十.线程状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NrkpNth1-1595654695657)(img/1.png)]

十一.同步合集

public class Main {
    public static void main(String[] args) {
        Collections.synchronizedCollection()//创建同步合集
        Collections.synchronizedList()//同步线性表
        Collections.synchronizedMap()//同步映射表
        Collections.synchronizedSet()//同步集合
        Collections.synchronizedSortedMap()
                
    }

}

十二.利用fork/join框架进行并行编程

  1. 用继承于RecursiveTask或RecursiveAction,其中一个可以返回值,然后重写里面compute方法
    其中的fork()表示创建一个异步任务分支,
    join()表示等待分支任务完成
    invoke()内部其实就是fork和join
    invokeAll(tasks)//多个分支
  2. 创建ForkJoinPool调用invoke()方法

实战1. 合并排序的并行实现和普通实现

import java.time.Instant;
import java.util.Arrays;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
public class Main {

    public static void main(String[] args){
        int[] arr=new int[50000000];
        for (int i = 0; i < 50000000; i++) {
            arr[i]=(int)(Math.random()*100+1);
        }
        long start2= Instant.now().toEpochMilli();
        new SortOther(arr).compute();
        long end2= Instant.now().toEpochMilli();
        System.out.println(end2-start2);
        long start1= Instant.now().toEpochMilli();
        ForkJoinPool forkJoinPool=new ForkJoinPool();
        forkJoinPool.invoke(new SortTask(arr));
        long end1= Instant.now().toEpochMilli();
        System.out.println(end1-start1);

    }
}
//普通实现
class SortOther{
    private int[] arr;
    public  static final int HOLD_THREAD=500;
    public  SortOther(int[] arr){
        this.arr=arr;
    }
    protected void compute() {
        if(arr.length<HOLD_THREAD){
            Arrays.sort(arr);
        }
        else {
            int[] firstArr=new int[arr.length/2];
            int[] lastArr=new int[arr.length-arr.length/2];
            System.arraycopy(arr, 0, firstArr, 0, arr.length/2);
            System.arraycopy(arr, arr.length/2, lastArr, 0, arr.length-arr.length/2);
            new SortOther(firstArr).compute();
            new SortOther(lastArr).compute();
            merge(firstArr, lastArr, arr);
        }

    }
    protected void merge(int[] first,int[] last,int[] list){
        System.arraycopy(first,0,list,0,first.length);
        System.arraycopy(last,0,list,first.length,last.length);
        Arrays.sort(list);
    }
}
//并行实现
class SortTask extends RecursiveAction {
    private int[] arr;
    public  static final int HOLD_THREAD=500;
    public  SortTask(int[] arr){
        this.arr=arr;
    }
    @Override
    protected void compute() {
        if(arr.length<HOLD_THREAD){
            Arrays.sort(arr);
        }
        else {
            int[] firstArr=new int[arr.length/2];
            int[] lastArr=new int[arr.length-arr.length/2];
            //0 1 2 3 4 5 6 7 8
            System.arraycopy(arr, 0, firstArr, 0, arr.length/2);
            System.arraycopy(arr, arr.length/2, lastArr, 0, arr.length-arr.length/2);
            invokeAll(new SortTask(firstArr),new SortTask(lastArr));
            merge(firstArr, lastArr, arr);
        }

    }
    protected void merge(int[] first,int[] last,int[] list){
        System.arraycopy(first,0,list,0,first.length);
        System.arraycopy(last,0,list,first.length,last.length);
        Arrays.sort(list);
    }
}

实战2 并行求和

import java.time.Instant;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class Main {

    public static void main(String[] args){
        long start2= Instant.now().toEpochMilli();
        ForkJoinPool forkJoinPool=new ForkJoinPool();
        long sum=forkJoinPool.invoke(new ParallelSum(0, 500000));
        System.out.println(sum);
        long end2= Instant.now().toEpochMilli();
        System.out.println(end2-start2);
    }
}
class ParallelSum extends RecursiveTask<Long> {
    public final  static int THREAD_HOLD=500;
    private long from;
    private long to;
    public ParallelSum(long from,long to){
        this.from=from;
        this.to=to;
    }
    @Override
    protected Long compute() {
        long len=to-from;
        if(len<=THREAD_HOLD){
            long sum=0;
            for (long i = from; i <to ; i++) {
                sum+=i;
            }
            return sum;
        }
        else {
            long middle=(from+to)/2;
            ParallelSum parallelSum=new ParallelSum(from,middle);
            ParallelSum parallelSum1=new ParallelSum(middle+1, to);
            parallelSum.fork();
            parallelSum1.fork();
            return parallelSum.join()+parallelSum1.join();
        }
    }
}

实战3 并行找最大值

import java.time.Instant;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class Main {

    public static void main(String[] args){
        int[] arr=new int[1000000];
        Random random=new Random(System.currentTimeMillis());
        for (int i = 0; i < 1000000; i++) {
            arr[i]=random.nextInt(9048);
        }
        long start2= Instant.now().toEpochMilli();
        ForkJoinPool forkJoinPool=new ForkJoinPool();
        
        long sum=forkJoinPool.invoke(new ParallelMax(arr));
        System.out.println(sum);
        long end2= Instant.now().toEpochMilli();
        System.out.println(end2-start2);
    }
}
class ParallelMax extends RecursiveTask<Integer> {
    public final  static int THREAD_HOLD=2;
    private int[] list;
    public  ParallelMax(int[] arr){
        list=arr;
    }
    @Override
    protected Integer compute() {
        if(list.length==THREAD_HOLD){
            return  Math.max(list[0],list[1]);
        }
        else  if(list.length==1){
            return list[0];
        }
        else  if(list.length==0){
            return null;
        }
        else {
            int[] first=new int[list.length/2];
            int[] last=new int[list.length-list.length/2];
            System.arraycopy(list, 0, first, 0, list.length/2);
            System.arraycopy(list, list.length/2, last, 0, list.length-list.length/2);
            ParallelMax parallelMax=new ParallelMax(first);
            ParallelMax parallelMax1=new ParallelMax(last);
            parallelMax.fork();
            parallelMax1.fork();
            return parallelMax.join()>parallelMax1.join()?parallelMax.join():parallelMax1.join();
        }

    }
}

实战4 并行统计文件大小

import java.io.File;
import java.time.Instant;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
public class Main {
    //普通递归
    public static long getDirSize(File dir) {
        if (dir == null) {
            return 0;
        }
        if (!dir.isDirectory()) {
            return 0;
        }
        long dirSize = 0;
        File[] files = dir.listFiles();
        if(files!=null){
            for (File file : files) {
                if (file.isFile()) {
                    dirSize += file.length();
                } else if (file.isDirectory()) {
                    dirSize += file.length();
                    dirSize += getDirSize(file); // 如果遇到目录则通过递归调用继续统计
                }
            }
        }
        return dirSize;
    }
    public static void main(String[] args){
        ForkJoinPool forkJoinPool=new ForkJoinPool();
        long start2= Instant.now().toEpochMilli();
        //long size=forkJoinPool.invoke(new ParallelFileSize(new File("C:\\")));
        long size=getDirSize(new File("C:\\"));
        long end2= Instant.now().toEpochMilli();
        System.out.println(size);
        System.out.println(end2-start2);
        long start1= Instant.now().toEpochMilli();
        long size1=forkJoinPool.invoke(new ParallelFileSize(new File("C:\\")));
        //long size=getDirSize(new File("C:\\"));
        long end1= Instant.now().toEpochMilli();

        System.out.println(end1-start1);
        System.out.println(size1);
    }

}
//并行递归
class ParallelFileSize extends RecursiveTask<Long>{
    private long size=0;
    private File file;
    public ParallelFileSize(File file){
        this.file=file;
    }
    @Override
    protected Long compute() {
        if(file==null){
            return null;
        }
        else {
            if(file.isFile()){
                size+=file.length();
            }
            else {
                File[] files=file.listFiles();
                if(files!=null){
                    ParallelFileSize[] parallelFileSizes =new ParallelFileSize[files.length];
                    for (int i = 0; i <files.length ; i++) {
                        parallelFileSizes[i]=new ParallelFileSize(files[i]);
                        parallelFileSizes[i].fork();
                    }
                    for (int i = 0; i <files.length ; i++) {
                        size+= parallelFileSizes[i].join();
                    }
                }
            }
        }
        return size;
    }
}
 private long size=0;
    private File file;
    public ParallelFileSize(File file){
        this.file=file;
    }
    @Override
    protected Long compute() {
        if(file==null){
            return null;
        }
        else {
            if(file.isFile()){
                size+=file.length();
            }
            else {
                File[] files=file.listFiles();
                if(files!=null){
                    ParallelFileSize[] parallelFileSizes =new ParallelFileSize[files.length];
                    for (int i = 0; i <files.length ; i++) {
                        parallelFileSizes[i]=new ParallelFileSize(files[i]);
                        parallelFileSizes[i].fork();
                    }
                    for (int i = 0; i <files.length ; i++) {
                        size+= parallelFileSizes[i].join();
                    }
                }
            }
        }
        return size;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值