线程池和lambda表达式

学习线程池和lambda表达式的理解

补充一个知识点(单例设计模式)

在多线程中,我们只需要一个任务类,为了防止创建多个任务类,这个时候就需要用到单例模式,单例模式有两种设计:

  1. 延迟加载(懒汉式)

    • 私有构造方法
    • 创建本类对象,但不初始化
    • 创建静态方法进行初始化对象并返回
  2. 立即加载(饿汉式)
    • 私有构造方法
    • 创建本类的对象并初始化(私有的)
    • 创建静态方法获取本类对象

下面用代码做个实例:

package com.wzlove.single;

/**
* 延迟加载(懒汉式)
* 1.私有构造方法
* 2.创建本类对象,但不初始化
* 3.创建静态方法进行初始化对象并返回
*
* 优点:
* 使用到类的对象才会加载,不消耗内存
* 缺点:
* 可能会出现线程安全问题,但是可以使用同步代码块消除这个安全问题
* @author WZLOVE
* @create 2018-07-19 10:36
*/
public class DeplayedSingle { // 私有构造方法
private DeplayedSingle(){} // 创建本类对象,不初始化
private static DeplayedSingle instance ; // 静态方法初始化
public static DeplayedSingle getInstance(){
synchronized (DeplayedSingle.class){
if(instance == null){
instance = new DeplayedSingle();
}
}
return instance;
}
} package com.wzlove.single; /**
* 立即加载(饿汉式)
* 1.私有构造方法
* 2.创建本类的对象并初始化(私有的)
* 3.创建静态方法获取本类对象
*
* 优点:
* 保证的线程的安全,没有线程安全问题
* 缺点:
* 使用类就会加载,比较消耗内存
* @author WZLOVE
* @create 2018-07-19 10:37
*/
public class ImmediateSingle { private ImmediateSingle(){} private static ImmediateSingle instance = new ImmediateSingle(); public static ImmediateSingle getInstance(){
return instance;
}
}

线程池

概述

线程池其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,

无需反复创建线程而消耗过多资源。作用是节省资源,原理是容器.

使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题.如果不使用线程池,

有可能造成系统创建大量同类线程而导致消耗完内存或者"过度切换"的问题.

创建线程池:

  • public static ExecutorService newFixedThreadPool(int nThreads) :返回线程池对象。(创建的是有界线

    程池,也就是池中的线程个数可以指定最大数量)
  • public Future<?> submit(Runnable task) :获取线程池中的某一个线程对象,并执行
  • Future接口:用来记录线程任务执行完毕后产生的结果。线程池创建与使用。

步骤:

  • 使用线程池的工厂类Executors里面提供静态方法newFixedThreadPool生产一个指定线程数量的线程池
  • 创建一个类,实现Runnable接口,重写run方法,设置线程任务
  • 调用ExecutorService中的方法submit,传递线程任务(实现类),开启线程(前提是线程池中有线程可用),执行run方法
  • 调用ExecutorService中的shutdown方法销毁线程池(不建议执行)

补充线程的创建

创建线程的第三种方式(这种方式很少见)

package com.wzlove.executor;

import java.util.ArrayList;
import java.util.concurrent.Callable; /**
* 线程的第三种创建方法
* Callable有返回值并且可以抛出异常
* @author WZLOVE
* @create 2018-07-18 14:14
*/
public class CallableImpl implements Callable<String> { private static ArrayList<String> arrayList = new ArrayList<>(); static{
arrayList.add("1");
} @Override
public String call() throws Exception {
return Thread.currentThread().getName();
}
} package com.wzlove.executor; import java.util.concurrent.*; /**
* 测试线程的第三中创建方式
*
* @author WZLOVE
* @create 2018-07-18 14:14
*/
public class Demo { public static void main(String[] args) {
// 创建实现Callable的实现类对象
Callable<String> callable = new CallableImpl();
// 创建FutureTask,并传递Callable接口的实现类对象
FutureTask task = new FutureTask(callable);
// 创建线程池对象
// ExecutorService executor = Executors.newSingleThreadExecutor();
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(callable);
// 执行线程
executor.execute(task); try {
System.out.println(task.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
} }

Lambda表达式

lambda体现的是一种函数式编程的思想, 它强调的是做什么,而不是以什么形式做。

使用前提

  • 使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。无论是JDK内置的Runnable 、Comparator 接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。
  • 使用Lambda必须具有上下文推断。也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。

有且仅有一个抽象方法的接口,称为“函数式接口”。

Lambda标准格式

Lambda省去面向对象的条条框框,格式由3个部分组成:

  • 一些参数
  • 一个箭头
  • 一段代码

Lambda表达式的标准格式为:

(参数类型 参数名称) ‐> { 代码语句 }

格式说明:

  • 小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔。
  • -> 是新引入的语法格式,代表指向动作。
  • 大括号内的语法与传统方法体要求基本一致。

线程匿名内部类的转化(无参无返回值)

实现Runnable接口的匿名内部类的实现:

public class Demo01Runnable {
public static void main(String[] args) {
// 匿名内部类
Runnable task = new Runnable() {
@Override
public void run() { // 覆盖重写抽象方法
System.out.println("多线程任务执行!");
}
};
new Thread(task).start(); // 启动线程
}
}

代码分析

  • Thread 类需要Runnable 接口作为参数,其中的抽象run 方法是用来指定线程任务内容的核心;
  • 为了指定run 的方法体,不得不需要Runnable 接口的实现类;
  • 为了省去定义一个RunnableImpl 实现类的麻烦,不得不使用匿名内部类;
  • 必须覆盖重写抽象run 方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错;
  • 而实际上,似乎只有方法体才是关键所在。

使用Lambda进行简化:

public class Demo01Runnable {
public static void main(String[] args) {
new Thread(()->System.out.println("多线程任务执行!")).start(); // 启动线程
}
}

比较器内部类的转化(有参有返回值)

使用比较器举个例子:

// 创建数组
Integer[] arr = {1,8,3,4,9,2,5}; // 匿名内部类实现数组升序排序
Arrays.sort(arr,new Comparator<Integer>(){ @Override
public int compare(Integer o1, Integer o2) {
return 0;
}
}); // 使用lambda进行数组的升序排序
Arrays.sort(arr,( a, b)->{ return a - b ;});

Lambda表达式的省略规则

在Lambda标准格式的基础上,使用省略写法的规则为:

  1. 小括号内参数的类型可以省略;
  2. 如果小括号内有且仅有一个参,则小括号可以省略;
  3. 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。

虽然有省略写法,但是我感觉这个有点灵活,所以不建议省略,因为代码是给别人看的,省略的话感觉别人看起来会有点费劲.

Java之线程池和Lambda表达式的更多相关文章

  1. Java【线程池、Lambda表达式】

    见pdf 等待唤醒机制 wait和notify 第二章 线程池 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低 系统的效率,因为频繁创建线程和销毁 ...

  2. JavaSE学习笔记(13)---线程池、Lambda表达式

    JavaSE学习笔记(13)---线程池.Lambda表达式 1.等待唤醒机制 线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同. 比如:线程A用来生成包子的,线程B用 ...

  3. 01 语言基础+高级:1-7 异常与多线程_day07 【线程池、Lambda表达式】

    day07[线程池.Lambda表达式] 主要内容 等待与唤醒案例 线程池 Lambda表达式 教学目标 -[ ] 能够理解线程通信概念-[ ] 能够理解等待唤醒机制-[ ] 能够描述Java中线程池 ...

  4. 328 day07线程池、Lambda表达式

    day07[线程池.Lambda表达式] 主要内容 等待与唤醒案例 线程池 Lambda表达式 教学目标 -[ ] 能够理解线程通信概念 -[ ] 能够理解等待唤醒机制 -[ ] 能够描述Java中线 ...

  5. 线程池、Lambda表达式

    线程池.Lambda表达式 线程池.Lambda表达式 线程池.Lambda表达式 线程池.Lambda表达式 线程池.Lambda表达式 线程池.Lambda表达式 线程池.Lambda表达式 (正 ...

  6. 线程池和lambda表达式

    线程池1.什么是线程池.一个用来创建和管理线程的容器;2.线程池的作用.提高线程的复用性,降低资源消耗提高线程的响应速度,提高线程的可管理性3.线程的核心思想;线程的复用 4.线程池的创建Execut ...

  7. Java线程池 与Lambda

    七.线程池.Lambda 1.1基本概念: ​ 线程池:其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多的资源. 1.2线程池的好处: ...

  8. Java 终于在 Java 8 中引入了 Lambda 表达式。也称之为闭包或者匿名函数。

    本文首发于 blog.zhaochunqi.com 转载请注明 blog.zhaochunqi.com 根据JSR 335, Java 终于在 Java 8 中引入了 Lambda 表达式.也称之为闭 ...

  9. 深入理解Java之线程池

    原作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本文归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...

随机推荐

  1. 我用Python远程探查室友的网页浏览记录,他不愧是成年人!

    过程: 利用Python制作远程查看别人电脑的操作记录,与其它教程类似,都是通过邮件返回. 利用程序得到目标电脑浏览器当中的访问记录,生产一个文本并发送到你自己的邮箱,当然这个整个过程除了你把pyth ...

  2. python-GUI之tkinter的学习

    最近看了哔哩哔哩的python的学习,直接看代码吧,以后会更新 先来个基础的 import tkinter as tk #导入包 app = tk.Tk() #抽象出一个GUI app.title(& ...

  3. jar包、war包

    JavaSE程序可以打包成Jar包(J其实可以理解为Java了),而JavaWeb程序可以打包成war包(w其实可以理解为Web了).然后把war发布到Tomcat的webapps目录下,Tomcat ...

  4. Netty源码分析第1章(Netty启动流程)---->第4节: 注册多路复用

    Netty源码分析第一章:Netty启动流程   第四节:注册多路复用 回顾下以上的小节, 我们知道了channel的的创建和初始化过程, 那么channel是如何注册到selector中的呢?我们继 ...

  5. 配置Ubuntu16.04虚拟机 (用途:CTF_pwn)

    因为学习需要16.xx的虚拟机,所以把之前18.04的Ubuntu卸掉重装了一遍Ubuntu16.04, 考虑到我有备份和重装系统的爱好,故记之,以备后用. 目录: //最后更新时间:190122·1 ...

  6. [奇葩问题] ERROR 2013 (HY000): Lost connection to MySQL server during query

    查询一条耗时30s以上语句,实际为2分钟多. mysql> select version(); +------------+ | version() | +------------+ | 5.6 ...

  7. 9.Hive Metastore Administration

    前言metastore参数metastore的基本参数metastore的额外参数客户端参数使用zk自动发现mestastore启动hive metastore服务 前言 本节讲metastore相关 ...

  8. iOS 开发学习-类的创建与实现,与java语言的对比

    Person.h #import <Foundation/Foundation.h> @interface Person : NSObject { //在{}中定义属性(全局变量/实例变量 ...

  9. mabatis报错 Result Maps collection already contains value for gamedataserver.dao.one.ChargeRecordMapper.BaseResultMap

    1.解决这种报错看看英文"already ",也就是已经存在,其实是因为存在了两个id相同的返回,以下可以看看,根据这种例子看看自己项目是不是这种问题

  10. mysql密码忘记解决方案

    方法:在忘记root密码的时候,可以这样 以windows为例: 1. 关闭正在运行的MySQL服务. 2. 打开DOS窗口,转到mysql\bin目录. 3. 输入mysqld --skip-gra ...