多线程共享数据

 多个线程行为一致共同操作一个数据,最经典的例子就是卖票

public class ShareData {
    private int num  =10;
    public synchronized void inc(){
        num++;
        System.out.println(Thread.currentThread().getName()+"调用inc这个方法num = "+num);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
package com.example.threadTest;

/**
 * Description: hibernate
 * Created by lenovo on 2019/6/1 19:33
 */
public class Ticket implements Runnable{
    private ShareData shareData;

    public Ticket(ShareData shareData) {
        this.shareData = shareData;
    }

    public Ticket() {

    }

    @Override
    public void run() {
        for (int i=0;i<5;i++){
            shareData.inc();
        }
    }
    public static void main (String[] args){
        ShareData shareData = new ShareData();
        for (int i=0;i<4;i++){
          new Thread(new Ticket(shareData),"Thread"+i).start();
      }
    }


}

2.多个线程行为不一致,共同操作一个数据

如果每个线程执行的代码不同这个时候就需要调用不同的Runnable对象,有两种方法实现这个Runnable对象之间的数据共享

,将共享数据封装在另外一个对象中,然后将这些对象逐一传递给各个Runnable对象 ,每一个线程对共享数据的操作方法也分配到那个对象身上去完成,这样就容易实现针对

该数据进行的各个操作的互斥和通信。

哎,先看实现再看这个总结就会恍然大悟。

在共享数据的对象里面添加不同的实现方法

 

package com.example.demo1;

/**
 * Description: hibernate
 * Created by lenovo on 2019/6/1 19:57
 */
public class MyThread implements Runnable{
    private SharaData sharaData;
    public MyThread() {

    }

    public MyThread(SharaData sharaData) {
        this.sharaData = sharaData;
    }

    public static void main (String[] args){

        SharaData sharaData = new SharaData();
        for (int i=0;i<4;i++){
            if (i%2==0){
                new Thread(new MyThread(sharaData),"Thread"+i).start();
            }else{
                new Thread(new MyThreadDec(sharaData),"Thread"+i).start();
            }
        }
    }
    //封装共享数据类



    @Override
    public void run() {
    for (int i=0;i<5;i++){
        sharaData.inc();

    }
    }
}

 

//
package com.example.demo1;
/** * Description: hibernate * Created by lenovo on 2019/6/1 20:07 */ public class MyThreadDec implements Runnable{ //封装共享数据 private SharaData sharaData; public MyThreadDec(SharaData sharaData) { this.sharaData = sharaData; } @Override public void run() { for (int i=0;i<5;i++){ sharaData.dec(); } } }
//共享数据类
package com.example.demo1;
/** * Description: hibernate * Created by lenovo on 2019/6/1 19:57 */ public class SharaData { private int num =10; public synchronized void inc(){ num++; System.out.println(Thread.currentThread().getName()+"调用inc这个方法num = "+num); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void dec(){ num++; System.out.println(Thread.currentThread().getName()+"调用inc这个方法num = "+num); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }

 

第二种方法

将这些Runnable对象作为一个类中的内部类,共享数据作为这个外部类中的成员变量,你每一个线程对共享数据的操作方法也分配给外部类,、

以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable对象调用外部类的这些方法

package com.example.demo1;

/**
 * Description: hibernate
 * Created by lenovo on 2019/6/1 20:33
 */
public class Thread2 {
    public static void main (String[] args){
        final SharaData sharaData =  new SharaData();
       for (int i=0;i<4;i++){
           if (i%2==0){
               new Thread(new Runnable() {
                   @Override
                   public void run() {
                       for (int i=0;i<5;i++){
                           sharaData.inc();
                       }
                   }
               },"Thread"+i).start();
           }else{
                 new Thread(new Runnable() {
                     @Override
                     public void run() {
                         for (int i=0;i<5;i++){
                             sharaData.dec();
                         }
                     }
                 },"Thread"+i).start();
           }
       }
    }

}

 分析java.util.concurrent  分析线程池工厂类

package com.example.demo1;

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

/**
 * 固定大小的线程池
 */
public class Thread3 {
    public static void main (String[] args){
        //创建一个可重用固定大小的线程池
        ExecutorService pool = Executors.newFixedThreadPool(2);
        //创建实现了Runnable接口的对象,Thread对象当然也实现了Runnable接口
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();
        MyThread t4 = new MyThread();
        MyThread t5 = new MyThread();
        //将线程放入池中进行执行
        pool.execute(t1);
        pool.execute(t2);
        pool.execute(t3);
        pool.execute(t4);
        pool.execute(t5);
        //关闭线程池
        pool.shutdown();
    }
}
pool-1-thread-1正在执行
pool-1-thread-1正在执行
pool-1-thread-1正在执行
pool-1-thread-1正在执行
pool-1-thread-2正在执行

通过这个结果可以看出,只有两个线程在执行,我们Thread类都是在线程池中运行的,线程池在执行execute方法来执行Thread类中的run方法不管execute

执行几次,线程池始终都会使用2个线程来处理,不会再去创建其他线程来处理run方法,这就是固定大小线程池。

 

单任务连接池


//创建一个可重用固定大小的线程池 //ExecutorService pool = Executors.newFixedThreadPool(2); ExecutorService pool = Executors.newSingleThreadExecutor(); //创建实现了Runnable接口的对象,Thread对象当然也实现了Runnable接口
pool-1-thread-1正在执行
pool-1-thread-1正在执行
pool-1-thread-1正在执行
pool-1-thread-1正在执行
pool-1-thread-1正在执行

从执行结果可以看出,单任务线程再执行execute()方法来执行Thread类中的run方法,不管exceute执行几次,线程池始终这都会使用单个线程来处理、。

 

可变连接池

   //创建一个可重用固定大小的线程池
        //ExecutorService pool = Executors.newFixedThreadPool(2);
      //  ExecutorService pool = Executors.newSingleThreadExecutor();
        ExecutorService pool = Executors.newCachedThreadPool();
        //创建实现了Runnable接口的对象,Thread对象当然也实现了Runnable接口
pool-1-thread-1正在执行
pool-1-thread-3正在执行
pool-1-thread-2正在执行
pool-1-thread-4正在执行
pool-1-thread-5正在执行

运行结果看出,可变任务线程池再执行Thread类中的run 方法这里的execute执行多次就会创建出多个线程来处理Thread类中的run方法,所有我们看到连接池

会根据执行情况在程序运行时创建多个线程来处理,这里就是可变连接池的特点

 

延迟连接池

package com.example.demo1;

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

/**
 * 固定大小的线程池
 */
public class Thread3 {
    public static void main (String[] args){
        //创建一个可重用固定大小的线程池
        //ExecutorService pool = Executors.newFixedThreadPool(2);
      //  ExecutorService pool = Executors.newSingleThreadExecutor();
       // ExecutorService pool = Executors.newCachedThreadPool();
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
        //创建实现了Runnable接口的对象,Thread对象当然也实现了Runnable接口
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();
        MyThread t4 = new MyThread();
        MyThread t5 = new MyThread();
        //将线程放入池中进行执行
        pool.execute(t1);
        pool.execute(t2);
        pool.execute(t3);
        //使用定时执行风格的执行方法
        pool.schedule(t4,10,TimeUnit.MILLISECONDS);//t4在10s后执行
        pool.schedule(t5,10,TimeUnit.MILLISECONDS);//t5在10s后执行
        //关闭线程池
        pool.shutdown();



    }
}

ExecuteService  执行器服务  

package com.example.demo1;

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

/**
 * 固定大小的线程池
 */
public class Thread3 {
    public static void main (String[] args){
        //创建一个可重用固定大小的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
      //  ExecutorService pool = Executors.newSingleThreadExecutor();
       // ExecutorService pool = Executors.newCachedThreadPool();
     //   ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
        //创建实现了Runnable接口的对象,Thread对象当然也实现了Runnable接口
      executorService.execute(new Runnable() {
          @Override
          public void run() {
              System.out.println("Asynchronous task");
          }
      });
      //线程池关闭
     executorService.shutdown();



    }
}

上面代码首先使用了newFixedThreadPoll()工厂方法创建了一个ExecutoService这里创建了一个10个线程的执行任务的线程池,然后讲一个Runnablle接口的匿名实现类

传递给execute()方法这刚导致Executor中的某个线程执行Runnable 这里可以看成一个任务分派,任务分派我们可以理解为一个线程将一个任务委派给ExecutorService去

异步执行,一旦该线程将任务为派给ExecutorService该线程将继续他自己的执行,独立于该任务的执执行。

ExecutorService的实现

ExecutorService 是一个接口,如果你想要使用它吗,就要去使用它的实现类之一

ThreadPollExecutor

ScheduledThreadPoolExecutor 

Executor 的创建步骤:

  ExecutorService executorService = Executors.newFixedThreadPool(10);
      //  ExecutorService pool = Executors.newSingleThreadExecutor();
       // ExecutorService pool = Executors.newCachedThreadPool();
     //   ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);

ExecutorService 的使用

有几种不同的方法来讲任务委托给ExecutorService来执行

execute(Runnable)

submit(Runnable)

submit(Callable)

invokeAll()

invokeAny()

execute(Runnable)的使用方法

package com.example.demo1;

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

/**
 * 固定大小的线程池
 */
public class Thread3 {
    public static void main (String[] args){
        //创建一个可重用固定大小的线程池
   //     ExecutorService executorService = Executors.newFixedThreadPool(10);
        ExecutorService executorService = Executors.newSingleThreadExecutor();
       // ExecutorService executorService = Executors.newCachedThreadPool();
     //   ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
        //创建实现了Runnable接口的对象,Thread对象当然也实现了Runnable接口
      executorService.execute(new Runnable() {
          @Override
          public void run() {
              System.out.println("Asynchronous task");
          }
      });
      //线程池关闭
     executorService.shutdown();



    }
}

submit(Runnable)的使用方法 也要求一个Runnable实现类,但它返回一个Future对象,这个Future对象可以用来检查Runnable是否已经执行完毕 

package com.example.demo1;

import java.util.concurrent.*;

/**
 * 固定大小的线程池
 */
public class Thread3 {
    public static void main (String[] args) throws ExecutionException, InterruptedException {
        //创建一个可重用固定大小的线程池
   //     ExecutorService executorService = Executors.newFixedThreadPool(10);
        ExecutorService executorService = Executors.newSingleThreadExecutor();
       // ExecutorService executorService = Executors.newCachedThreadPool();
     //   ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
        //创建实现了Runnable接口的对象,Thread对象当然也实现了Runnable接口
      Future future = executorService.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("Asynchronous task");
            }
        });
      future.get();//获得执行完run方法后的返回值,这里使用的Runnable所以这里没有返回值,返回的是null
     /* executorService.execute(new Runnable() {
          @Override
          public void run() {
              System.out.println("Asynchronous task");
          }
      });*/
      //线程池关闭
     executorService.shutdown();



    }
}

submit(Calable)  方法类似于submit(Runnable)方法,除了他所要求的参数类型之外,Callable实例除了它的call()得到能够返回一个结果之外和一个Runable很相像,Rannable.run()

不能够返回一个结果,Callable的结果可以通过submit(Callable) 方法返回的Future对象进行获取。

public class Thread3 {
    public static void main (String[] args) throws ExecutionException, InterruptedException {
        //创建一个可重用固定大小的线程池
   //     ExecutorService executorService = Executors.newFixedThreadPool(10);
        ExecutorService executorService = Executors.newSingleThreadExecutor();
       // ExecutorService executorService = Executors.newCachedThreadPool();
     //   ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
        //创建实现了Runnable接口的对象,Thread对象当然也实现了Runnable接口
        Future future =    executorService.submit(new Callable() {
            @Override
            public Object call() throws Exception {
                System.out.println("Asynchronous task");
                return "Callabled Result";
            }
        });
        System.out.println("Futural.get() = "+future.get());
        executorService.shutdown();
}
Asynchronous task
Futural.get() = Callabled Result

能拿到结果的返回值,这个就是很好的结果了

invokeAny() 这个方法要求一系列的Callable或者其子接口的实例对象,调用这个方法并不会返回一个Future,但它返回其中一个Callable对象的结果

无法保证返回的是哪个Callable的结果,只能表明其中一个以执行结束

如果其中一个任务执行结束,其他Callble将被取消

public class Thread3 {
    public static void main (String[] args) throws ExecutionException, InterruptedException {
        //创建一个可重用固定大小的线程池
   //     ExecutorService executorService = Executors.newFixedThreadPool(10);
        ExecutorService executorService = Executors.newSingleThreadExecutor();
       // ExecutorService executorService = Executors.newCachedThreadPool();
     //   ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
        //创建实现了Runnable接口的对象,Thread对象当然也实现了Runnable接口
        HashSet<Callable<String>> callables = new HashSet<>();

        callables.add(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "Test 1";
            }
        });
        callables.add(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "Test 2";
            }
        });
        callables.add(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "Test 3";
            }
        });
        String result = executorService.invokeAny(callables);
        System.out.println("result="+result);
        executorService.shutdown();

}
result=Test 1

invokeAll()  这个方法将调用你在集合中传给ExecutorService 所有的Callabld对象 invokleAll()返回一系列的Future 对象,通过他们你们可以获取每一个Callabled的执行结果

记住,一个任务可能会由一个异常而结束,因而他可能没有成功,无法通过一个Future对象我们是两种结束中的哪一种

public class Thread3 {
    public static void main (String[] args) throws ExecutionException, InterruptedException {
        //创建一个可重用固定大小的线程池
   //     ExecutorService executorService = Executors.newFixedThreadPool(10);
        ExecutorService executorService = Executors.newSingleThreadExecutor();
       // ExecutorService executorService = Executors.newCachedThreadPool();
     //   ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
        //创建实现了Runnable接口的对象,Thread对象当然也实现了Runnable接口
        HashSet<Callable<String>> callables = new HashSet<>();

        callables.add(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "Test 1";
            }
        });
        callables.add(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "Test 2";
            }
        });
        callables.add(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "Test 3";
            }
        });
       List<Future<String>> futures= executorService.invokeAll(callables);
       for (Future<String> future:futures){
           System.out.println("Future.get="+future.get());

       }
        executorService.shutdown();
Future.get=Test 1
Future.get=Test 2
Future.get=Test 3

Executors 关闭

使用shutdown shutdownNow 可以关闭线程

shutdown() 只能将空闲的线程interrupt()了,shutdown()之前提交的任务可以继续执行到结束,shutdownNow()是interrupt所有的线程因此大部分线程

将立刻被中断,之所以是大部分而不是全部是因为interrupt()方法能力有限。

ThreadPoolExecutor 线程池执行者

java.util.Concurrent.ThreadPoolExecutor 是ExecutorService接口的实现ThreadPoolExecuitor使用内部池中的线程执行给定的任务(Callable 或者Runnable)

里面有连个方法 corePoolSize

                         MaxMumPoolSize

当一个任务委托给线程池时,如果池中线程数量低于corePoolSize 一个新的线程将被创建,即使池中可能存有空闲线程,如果内部任务队列已满,而且有至少corePoolSize正在

运行,但是运行线程的数量低于maxMumpoolSize 一个新的线程将被创建去执行该任务。 

package com.example.demo1;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Description: hibernate
 * Created by lenovo on 2019/6/1 22:05
 */
public class Thread4 {
    public static void main (String[] args){
      int corePoolSize  = 5;
      int maxPoolSize  = 10;
      long keepAliveTime  = 5000;
      new ThreadPoolExecutor(
              corePoolSize,  //池中所保存的线程是
              maxPoolSize,   //池中允许的最大线程数
              keepAliveTime,  //线程数大于核心线程数时,此为终止前多余的空闲线程等待新任务的最长时间
              TimeUnit.MILLISECONDS, //参数的时间单位
              new LinkedBlockingQueue<Runnable>() //执行前用于保持任务的队列,次队列仅保持由execute方法
              //提交的Runnable任务。
      );
    }
}

ScheduledPoolExecutor 定时线程池执行者

java.util.concurrent.ScheduledExecutorService 是一个ExecutorService 他能够将任务延后执行,或者间隔固定时间多次执行。任务由一个工作者线程一步之幸,而不是由

交给任务给ScheduledExecutorService的那个线程执行。

 

package com.example.demo1;

import ch.qos.logback.core.util.ExecutorServiceUtil;
import com.sun.org.apache.xalan.internal.utils.FeatureManager;

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

/**
 * Description: hibernate
 * Created by lenovo on 2019/6/2 7:07
 */
public class Thread5 {
    public static void main (String[] args){
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
    scheduledExecutorService.schedule(new Callable() {
            @Override
            public Object call() throws Exception {
                return "Called";
            }
        },5, TimeUnit.SECONDS);//5秒后执行

      scheduledExecutorService.shutdown();

    }
}

首先一个内置5个线程 的SchedualExecutorService被创建,之后一个Callable接口的匿名类实例被创建,然后传递给schedual()方法后边的俩参数定义了Callable将在

5秒之后被执行。

SchedualExecutorService的实现

SchedualExecutorService是一个接口

 SchedualExecutorService的使用

 

 schedual(Callable  task,long dely,TimeUnite timeunite)

schedual(Runnable,long initialDely,long period,TimeUnit   timeunit)

schedualAtFixedRate(Rannable,long initDely,long peiod ,TimeUnit   timeunit)

schedualWithFixedDely(Runnable,long initialDely,long period,TimeUnit timenit)

 

schedual(Runnable,long initialDely,long period,TimeUnit   timeunit)

package com.example.demo1;

import ch.qos.logback.core.util.ExecutorServiceUtil;
import com.sun.org.apache.xalan.internal.utils.FeatureManager;

import java.util.concurrent.*;

/**
 * Description: hibernate
 * Created by lenovo on 2019/6/2 7:07
 */
public class Thread5 {
    public static void main (String[] args){
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
  ScheduledFuture scheduledFuture = scheduledExecutorService.schedule(new Callable() {
            @Override
            public Object call() throws Exception {
                System.out.println("Executed");
                return "Called";
            }
        },5, TimeUnit.SECONDS);//5秒后执行
        try {
            System.out.println("result"+scheduledFuture.get());

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        scheduledExecutorService.shutdown();

    }
}

schedual(Runnable,long initialDely,long period,TimeUnit   timeunit)

这个方法规划一个任务将被定期执行,改任务将会在首个initialDely之后执行,然后每个period之后重复执行,如果给定任务的执行跑出了异常,改任务将不再执行

如果没有任何异常的话,这个任务将会持续循环执行到SchedualExceptionService被关闭

如果一个任务占用了比计划的时间间隔更长的时候,下一次执行将在当前执行结束执行草开始,计划任务在同一时间不会有多个线程同时执行。

 

schedualAtFixedRate(Runnable,long initialDely,long period,TimeUnit timeunit)

这一方法规划一个任务将被定期执行,该任务将会在首个initnialDely之后得到执行,然后每个period时间之后重复执行,如果给定任务的执行抛出了异常,该任务将不再执行、

如果没有任何异常,这个任务将会持续循环执行到SchedualExecutorService被关闭

如果一个任务占用了比计划的时间间隔更长的时间的时候,下一次执行将在当前执行结束执行才开始,几乎任务在同一时间不会有多个线程同时执行。

 

 schedualWithFixedDely(Rannable ,long initialDely,long period,TimeUnite timeunite)

除了period 有不同的解释之外这个方法和schedaulFixedRate()非常像,schedualAtFixedRate()方法中peiod被解释为前一个执行的开始和下一个执行的开始之间的间隔时间

而在本方法中period被解释为前一个执行的结束,和下一个执行的开始的间隔,而不是执行开始之间的间隔。

 

SchedualExecutorService之间的关闭 

shutdown()  shutdownNow()

在你使用结束后需要把它关闭掉,否则他将会导致JVM继续运行,即使所有其他线程已经全被关闭

ForkJoinPool   合并和分叉  线程池

ForkJoinPool在java 7中被引入,他和ExecutorService很像,他可以很方便的把任务分成几个更小的任务,这些分裂出来的任务也将会提交给ForkJoinPool

任务可以继续分割成小任务,这些子任务可以被并发执行。每一个子任务可以有不同的cpu并行执行,或者被同一个cpu上的不同线程执行,只有当给的任务过大、

把它分割成几个子任务才有意义,把任务分割成几个子任务有一定的开销,因此对于小型任务,这个分割的消耗可能比每个子任务并发执行  执行的消耗还要大

 

合并就是当所有子任务执行结束后,将执行结果合并到同一个结果中。,如果这个子任务没有返回值,只需要等待其他子任务执行完毕,也就不需要结果的合并。

两种任务一种是有返回值的任务,另外一种是没有返回值的任务 RecursiveAction RecursiveTask 

package com.example.demo2;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.RecursiveAction;

/**
 * Description: hibernate
 * Created by lenovo on 2019/6/2 8:47
 */
public class MyRecursiveAction extends RecursiveAction {
  private long workload =0;

    public MyRecursiveAction(long workload) {
        this.workload = workload;
    }

    @Override
    protected void compute() {
        //如果工作超过门槛,把任务分解成更小的任务
        if (this.workload>16){
            System.out.println("splitting workLoad"+this.workload);
            ArrayList<MyRecursiveAction> subTasks = new ArrayList<>();
            subTasks.addAll(creatSubtasks());

            for (RecursiveAction subTask:subTasks ){
                subTask.fork();

            }
        }
        else{
            System.out.println("Doing workLoad myself: "+this.workload);
        }

    }

    private List< MyRecursiveAction> creatSubtasks() {
        ArrayList<MyRecursiveAction> subTasks = new ArrayList<>();
        MyRecursiveAction subTask1 = new MyRecursiveAction(this.workload / 2);
        MyRecursiveAction subTask2 = new MyRecursiveAction(this.workload / 2);
        subTasks.add(subTask1);
        subTasks.add(subTask2);
        return subTasks;


    }
}
package com.example.demo2;

import java.util.concurrent.ForkJoinPool;

/**
 * Description: hibernate
 * Created by lenovo on 2019/6/2 8:58
 */
public class MyForkJoinPool {
    public static void main (String[] args){
       //创建一个并行级别为4的forkJoinPool

        ForkJoinPool forkJoinPool = new ForkJoinPool();

        //创建一个没有返回值的任务
        MyRecursiveAction myRecursiveAction = new MyRecursiveAction(24);

        //ForkJoinPool执行任务
        forkJoinPool.invoke(myRecursiveAction);
    }
}
splitting workLoad24
Doing workLoad myself: 12
Doing workLoad myself: 12

RecurSiveTask  是一种会返回结果的任务,他可以将自己的工作分割为若干更小的任务,并将这些子任务的执行结果合并到一个集合结果,可以有结果水平的分割和合并、

package com.example.demo2;

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

/**
 * Description: hibernate
 * Created by lenovo on 2019/6/2 9:08
 */
public class MyRecurSiveTask extends RecursiveTask {
    private long workLoad =0;

    public MyRecurSiveTask(long workLoad) {
        this.workLoad = workLoad;
    }


    @Override
    protected Object compute() {

        if (this.workLoad>16){
            System.out.println("spling workLoad" +this.workLoad);
            ArrayList<MyRecurSiveTask> subTasks = new ArrayList<>();

            subTasks.addAll(creatSubTasks());
            for (MyRecurSiveTask subTask : subTasks){
                subTask.fork();
            }
            long result =0;
            for (MyRecurSiveTask subTask:subTasks){
             result += (long) subTask.join();
            }
            return result;
        }else{
            System.out.println("Doing workLoad myself:"+this.workLoad);

            return workLoad*3;
        }

    }

    private List< MyRecurSiveTask> creatSubTasks() {
        ArrayList<MyRecurSiveTask> subTasks = new ArrayList<>();
        MyRecurSiveTask subTask1 = new MyRecurSiveTask(this.workLoad / 2);
        MyRecurSiveTask subTask2 = new MyRecurSiveTask(this.workLoad / 2);
        subTasks.add(subTask1);
        subTasks.add(subTask2);

        return subTasks;
    }
}
package com.example.demo2;

import java.util.concurrent.ForkJoinPool;

/**
 * Description: hibernate
 * Created by lenovo on 2019/6/2 8:58
 */
public class MyForkJoinPool {
    public static void main (String[] args){
       //创建一个并行级别为4的forkJoinPool

        ForkJoinPool forkJoinPool = new ForkJoinPool(4);

        //创建一个没有返回值的任务
       // MyRecursiveAction myRecursiveAction = new MyRecursiveAction(24);

        //创建一个有返回值的任务
        MyRecurSiveTask myRecurSiveTask = new MyRecurSiveTask(128);



        //ForkJoinPool执行任务
        long mergeResult = (long) forkJoinPool.invoke(myRecurSiveTask);

        System.out.println("mergeResult"+mergeResult);
    }
}

ForkJoinPool.invoke 方法的调用来获取最终的执行结果

并发队列,阻塞队列

常用的并发队列有阻塞队列和非阻塞队列,前者使用锁实现,后者使用CAS非阻塞算法实现

阻塞队列 (Bloking Queue)   java.util.concurrent 包下的重要数据结构  Bloking Queue 提供了线程安全的队列访问方式,当阻塞队列进行插入数据时,如果队列已满,线程将会阻塞等待直到队列非满,从阻塞队列取数据时,如果队列已空,线程将会阻塞等待直到队列非空,并发包下的很多高级同步类的实现都是基于BlokingQueue实现的

 

BlokingQueue通常用于一个线程生产对象,而另外一个线程消费这些对象的场景。一个线程将会持续生产新对象并将其插入到队列之中,直到队列达到他所能容纳的零界点、之后就会产生阻塞,直到负责消费的线程从队列中拿走一个对象,如果消费线程从空的队列中提取对象,这个消费线程将会处于阻塞状态,直到一个生产线程把一个对象丢进队列。

  阻塞队列提供了4种处理方法

方法/处理方法 抛出异常 返回特殊值 一直阻塞 超时退出
插入方法 add(e) offer(e) put(e) offer(e,time,unit)
移除方法 remove() poll() take() poll(time,unit)
检查方法 element() peek() 不可用 不可用

 

 

四组不同的行为方式解释

抛异常:如果试图的操作无法立即执行,抛出一个异常

特定值:如果试图的操作无法立即执行,返回一个特定的值(常是true /false)

阻塞:如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行

超时:如果试图的操作无法立即执行 该方法调用将会发生阻塞,直到能够执行,单等待时间不会超过给定值,返回一个特定值已告知该操作是否成功。(true/false)

 

无法向一个BlockingQuqu中插入null,如果你试图插入null BlockingQueue将会抛出一个nullPointException.

 公平锁 :在并发环境中每一个线程在获取锁时会先查看此锁维护的等待队列,如果为空 或者当前线程是等待的第一个就占有锁,否则就会加入等待队列汇中

以后会按FIFO的规则从队列中取到自己。

ArrayBlockingQeue方法,如果队列满则返回false,否则返回true

 

 

 

 

 

 

 

 

非公平锁

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

                                                                                                                                                                                                                                                                                                   

 

posted @ 2019-06-01 20:39  纳兰容若♫  阅读(766)  评论(0编辑  收藏  举报