JUC-04-线程池,四大函数式接口,Stream流式计算

目录

    • 01、线程池
      • 概述
      • java.util.concurrent.Executors创建线程池:不推荐
      • java.util.concurrent.ThreadPoolExecutor 创建线程池:推荐
      • 线程池拓展
    • 02、四大函数式接口
      • 概述
      • 四大函数式接口之一:java.util.function.Function
      • 四大函数式接口之一: java.util.function.Predicate
      • 四大函数式接口之一:java.util.function.Consumer
      • 四大函数式接口之一:java.util.function.Supplier
    • 03、Stream流式计算:java.util.stream.Stream

01、线程池

概述

创建线程池:3大方法、7大参数、4 种拒绝策略

  • Executors创建线程池:里面有三大方法
  • ThreadPoolExecutor创建线程池:七大参数四种拒绝策略

池化技术:

  • 程序的运行本质,占用系统的资源, 优化资源的使用=>池化技术
  • 线程池、连接池、内存池、对象池。。。 创建、销毁,十分浪费资源
  • 池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。

线程池的好处:

  • 1、降低资源的消耗
  • 2、提高响应的速度
  • 3、方便管理。

线程复用、可以控制最大并发数、管理线程

java.util.concurrent.Executors创建线程池:不推荐

Executors工具类中提供了创建线程池的三大方法,如果打开源码进行查看会发现,它们内部使用的使用的还是ThreadPoolExecutor来创建的线程池,就好比使用ThreadPoolExecutor创建线程池的阉割版一样因此不建议使用

下面来看看这三个创建线程池的方法的源码:

  • Executors.newSingleThreadExecutor():创建单个线程
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
  • Executors.newFixedThreadPool(5):创建一个固定的线程池大小
 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
  • Executors.newCachedThreadPool():可伸缩的线程池
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式去创建,这样写让其他人更加明确线程的运行规则,规避资源耗尽的风险

Executors【返回线程池】的弊端如下:

  • FixedThreadPoolSingleThreadPool允许的请求对列长度为Integer.MAX_VALUE,可能会堆积大量的请求造成OOM
  • CachedThreadPoolCheduledThreadPool允许创建的线程数量为Integer.MAX_VALUE,可能会创建大量的线程造成OOM

演示代码:

public class ThreadPoolTest01 {
    public static void main(String[] args) {
        ExecutorService threadPool01=Executors.newSingleThreadExecutor();//单个线程
        ExecutorService threadPool02=Executors.newFixedThreadPool(5);//创建一个固定的线程池大小
        ExecutorService threadPool03=Executors.newScheduledThreadPool(2);
        ExecutorService threadPool04=Executors.newCachedThreadPool();//可伸缩的
        try {
            for(int i=0;i<10;i++){
            	//在此处修改使用哪个方法创建的线程池
                threadPool01.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"   OK!!!");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();//线程池使用完需要关闭
        }
    }
}

java.util.concurrent.ThreadPoolExecutor 创建线程池:推荐

七大参数:

  • ThreadPoolExecutor(使用这个来创建线程池):构造方法里面有七个参数
 public ThreadPoolExecutor(int corePoolSize,//核心线程池大小
                           int maximumPoolSize,//最大核心线程池大小
                           long keepAliveTime,//没人调用时的存活时间,过期自动释放
                           TimeUnit unit,//超时单位
                           BlockingQueue<Runnable> workQueue,//阻塞对列
                           ThreadFactory threadFactory, //创建工厂,用来创建线程,一般不动
                           RejectedExecutionHandler defaultHandler)//【拒绝策略】
                           {
      this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,threadFactory, defaultHandler);
  }

四种拒绝策略:

  • RejectedExecutionHandler接口的四个实现类,也是ThreadPoolExecutor类中的内部子类(使用默认的拒绝策略即可)

默认拒绝策略:AbortPolicy()

JUC-04-线程池,四大函数式接口,Stream流式计算_第1张图片
JUC-04-线程池,四大函数式接口,Stream流式计算_第2张图片

不同拒绝策略的区别:

  • new ThreadPoolExecutor.AbortPolicy() :队列满了,在创建线程,不处理这个创建过程的,抛出异常

最大承载线程个数:最大核心线程池+阻塞对列

  • new ThreadPoolExecutor.CallerRunsPolicy() :哪来的去哪里
  • new ThreadPoolExecutor.DiscardPolicy() :队列满了,丢掉任务,不会抛出异常
  • new ThreadPoolExecutor.DiscardOldestPolicy() :队列满了,尝试去和最早的竞争,也不会抛出异常!

代码演示

public class ThreadPoolTest01 {
    public static void main(String[] args) {
        ExecutorService threadPool=new ThreadPoolExecutor(2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());

        try {
            //最大承载:Deque+max-->3+5,超出会报异常
            //触发max的条件:corePoolSize+Deque>max
            for(int i=0;i<10;i++){
                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"   OK!!!");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();//线程池使用完需要关闭
        }
    }
}

线程池拓展

  • 自定义线程池使用: ThreadPoolExecutor
  • 最大线程到底该如何定义?
    • 1、CPU 密集型(可以并行执行多少条线程):几核,就是几,可以保持CPU的效率最高
    • 2、IO 密集型:判断你程序中十分耗IO的线程有多少个,大于这个数就行

代码演示:

public class Demo02 {
    public static void main(String[] args) {
        // 获取CPU的核数
        System.out.println(Runtime.getRuntime().availableProcessors());
        //创建线程池
        ExecutorService threadPool=new ThreadPoolExecutor(2,
                3,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());//AbortPolicy是一个内部类

        try {
            for(int i=0;i<6;i++){
               threadPool.execute(()->{
                   System.out.println(Thread.currentThread().getName()+" OK!!!");
               });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }
    }
}

02、四大函数式接口

概述

新时代的程序员要掌握的技能:

  • ambda表达式
  • 链式编程
  • 函数式接口
  • Stream流式计算

函数式接口: 只有一个方法的接口
四大函数式接口:java.util.function包下的四个原生的接口

  • Consumer接口
  • Function接口
  • Predicate接口
  • Supplier接口

四大函数式接口之一:java.util.function.Function

@FunctionalInterface
public interface Function<T, R> { .....}
  • 传入的参数的泛型T,返回的参数泛型R, 不写默认是Object类型
  • Function 函数型接口,有一个输入参数,有一个输出参数
  • 只要是 函数型接口都可以用lambda表达式简化

代码示例:

public class FunctionDemo1 {
    public static void main(String[] args) {
        //工具类:输出输入的值
        //普通使用方法
       Function function01= new Function<String,String>() {
            @Override
            public String apply(String string) {
                return string;
            }
        };
        System.out.println(function01.apply("aismall"));
        //使用Lambda表达式
        Function<String,String> function02=(str)->{return str;};
        System.out.println(function02.apply("aismall"));
    }
}

四大函数式接口之一: java.util.function.Predicate

@FunctionalInterface
 public interface Predicate<T> {.....}
  • 断定型接口:有一个输入参数,返回值只能是布尔值

代码示例:

public class PredicateDemo2 {
    public static void main(String[] args) {
        //工具类:判断字符串是否为空,为空返回true
       Predicate predicate01= new Predicate<String>(){
           @Override
           public boolean test(String s) {
               return s.isEmpty();
           }
       };
       System.out.println(predicate01.test(""));

       Predicate<String> predicate02=(str)->{return  str.isEmpty();};
       System.out.println(predicate02.test("aismall"));
    }
}

四大函数式接口之一:java.util.function.Consumer

@FunctionalInterface
 public interface Consumer<T> {......}
  • Consumer 消费型接口:只有输入,没有返回值

代码演示:

public class ConsumerDemo3 {
    public static void main(String[] args) {
        Consumer<Integer> consumer01=new Consumer<Integer>() {
            @Override
            public void accept(Integer num) {
                int a=num+666;
                System.out.println(a);
            }
        };
        consumer01.accept(100);

        Consumer<Integer> consumer02=(num)->{
            int a=num+666;
            System.out.println(a);
        };
        consumer02.accept(100);//没有输出结果
    }
}

四大函数式接口之一:java.util.function.Supplier

@FunctionalInterface
 public interface Supplier<T> {.....}
  • Supplier 供给型接口:没有参数,只有返回值

代码演示:

public class SupplierDemo4 {
    public static void main(String[] args) {
       Supplier<Test> supplier01=new Supplier<Test>() {
            @Override
            public Test get() {
            Test test01 =new Test();
            return test01;
            }
        };

       Test test01=supplier01.get();
       test01.show();


        Supplier<Test> supplier02=()->{
        Test test02 =new Test();
        return test02;
        };
        Test test02=supplier02.get();
        test02.show();
     }
}
class Test{
    public void show(){
        System.out.println("Supplier接口测试。。。");
    }
}

03、Stream流式计算:java.util.stream.Stream

  • java.util.stream包

流式计算:类似于水流一样,然后我们对水进行处理,一级一级的进行过滤

代码演示:

public class User {
    //有参,无参,get,set,toString
    private int id;
    private String name;
    private int age;
}
public class Test {
    public static void main(String[] args) {
        User u1 = new User(1,"a",21);
        User u2 = new User(2,"b",22);
        User u3 = new User(3,"c",23);
        User u4 = new User(4,"d",24);
        User u5 = new User(6,"e",25);
        //创建一个集合存储这些User
        List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
        // 计算交给Stream流
        // lambda表达式、链式编程、函数式接口、Stream流式计算
        list.stream()
                //找出id是偶数的
                .filter(u->{return u.getId()%2==0;})
                //年龄大于23
                .filter(u->{return u.getAge()>23;})
                //将名字转换为大写
                .map(u->{return u.getName().toUpperCase();})
                //只要第一个
                .limit(1)
                //打印输出
                .forEach(System.out::println);
    }
}

你可能感兴趣的:(java并发编程相关,lambda,java,多线程)