Java 线程

线程使程序能够通过同时执行多个任务而更有效地运行。

线程可用于在不中断主程序的情况下在后台执行复杂的任务。

创建线程

有两种创建线程的方式。

  1. 扩展Thread类

可以通过扩展Thread类并覆盖其run()方法来创建线程:

public class MyThread extends Thread {
public void run() {
System.out.println("This code is running in a thread");
}
}
  1. 实现Runnable接口

另一种创建线程的方式是实现Runnable接口:

public class MyRunnable implements Runnable {
public void run() {
System.out.println("This code is running in a thread");
}
}

运行线程

  1. 扩展Thread类

如果类扩展Thread类,则可以通过创建类的实例并调用其start()方法来运行线程:

public class Main {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
System.out.println("This code is outside of the thread");
}
}
  1. 实现Runnable接口

如果类实现了Runnable接口,则可以通过将类的实例传递给Thread对象的构造函数,然后调用线程的start()方法来运行线程:

public class Main {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
System.out.println("This code is outside of the thread");
}
}

区分“扩展”和“实现”线程

主要区别在于,当一个类扩展Thread类时,无法扩展任何其他类,但通过实现Runnable接口,可以扩展另一个类,例如:

class MyClass extends OtherClass implements Runnable

并发问题

因为线程与程序的其他部分同时运行,所以无法知道代码将按照什么顺序运行。当线程和主程序同时读取和写入相同的变量时,值是不可预测的。由此导致的问题称为并发问题。

示例

一个变量amount值不可预测的代码示例:

public class Main extends Thread {
public static int amount = 0; public static void main(String[] args) {
Main thread = new Main();
thread.start();
System.out.println(amount);
amount++;
System.out.println(amount);
} public void run() {
amount++;
}
}

为避免并发问题,最好尽可能少地在线程之间共享属性。如果需要共享属性,一种可能的解决方案是在使用线程可以更改的任何属性之前,使用线程的isAlive()方法检查线程是否已完成运行。

示例

使用isAlive()防止并发问题:

public class Main extends Thread {
public static int amount = 0; public static void main(String[] args) {
Main thread = new Main();
thread.start();
// 等待线程完成
while (thread.isAlive()) {
System.out.println("Waiting...");
}
// 更新amount并打印其值
System.out.println("Main program: " + amount);
amount++;
System.out.println("Main program: " + amount);
} public void run() {
amount++;
}
}

线程池

线程池是一种管理线程的资源。它允许您创建并维护一组可重用的线程。使用线程池可以提高应用程序的性能和效率。

线程安全

线程安全是指多个线程可以访问和修改数据而不导致数据损坏。使数据线程安全的一种方法是使用同步。同步是一种机制,它允许线程一次一个地访问共享数据。

常见的线程安全问题

  • 竞态条件:当多个线程同时访问共享数据并尝试对其进行更改时,就会发生竞态条件。这可能导致数据损坏。
  • 原子性:原子操作是指不可分割的操作。当多个线程尝试同时执行原子操作时,可能会导致数据损坏。
  • 可见性:当一个线程对共享数据进行更改时,其他线程必须能够看到这些更改。

避免线程安全问题

  • 使用同步
  • 使用不可变对象
  • 使用原子操作

Java Lambda表达式

Lambda表达式简介

Lambda表达式是在Java 8中引入的。Lambda表达式是一小段代码块,它接受参数并返回一个值。Lambda表达式类似于方法,但它们不需要名称,并且可以直接在方法体中实现。

Lambda表达式的语法

最简单的Lambda表达式包含一个参数和一个表达式:

参数 -> 表达式

要使用多个参数,请将它们放在括号中:

(参数1, 参数2) -> 表达式

表达式是有限制的。它们必须立即返回一个值,并且不能包含变量、赋值或if或for等语句。为了执行更复杂的操作,可以使用带有花括号的代码块。如果Lambda表达式需要返回一个值,那么代码块应该有一个return语句。

(参数1, 参数2) -> { 代码块 }

Lambda表达式的使用

Lambda表达式通常作为参数传递给函数。在以下示例中,Lambda表达式作为参数传递给ArrayList的forEach()方法,以打印列表中的每个项:

import java.util.ArrayList;

public class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(5);
numbers.add(9);
numbers.add(8 );
numbers.add(1);
numbers.forEach((n) -> { System.out.println(n); });
}
}

Lambda表达式的存储

如果变量的类型是仅具有一个方法的接口,那么Lambda表达式可以存储在变量中。Lambda表达式应该具有与该方法相同数量的参数和相同的返回类型。Java内置了许多这类接口,如Consumer接口(在java.util包中),它被列表使用。

import java.util.ArrayList;
import java.util.function.Consumer; public class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(5);
numbers.add(9);
numbers.add(8);
numbers.add(1);
Consumer<Integer> method = (n) -> { System.out.println(n); };
numbers.forEach(method);
}
}

Lambda表达式作为方法参数

要在方法中使用Lambda表达式,该方法应该有一个以单一方法接口作为其类型的参数。调用接口的方法将运行Lambda表达式。

interface StringFunction {
String run(String str);
} public class Main {
public static void main(String[] args) {
StringFunction exclaim = (s) -> s + "!";
StringFunction ask = (s) -> s + "?";
printFormatted("Hello", exclaim);
printFormatted("Hello", ask);
} public static void printFormatted(String str, StringFunction format) {
String result = format.run(str);
System.out.println(result);
}
}

Lambda表达式的优势

  • 简化代码
  • 提高可读性
  • 增强代码的表达力

Lambda 表达式是 Java 8 中引入的一项强大功能,可以简化代码并提高可读性。它们是函数式编程的重要组成部分,可以用于各种任务,例如数据处理、事件处理和流处理。

最后

为了方便其他设备和平台的小伙伴观看往期文章:

微信公众号搜索:Let us Coding,关注后即可获取最新文章推送

看完如果觉得有帮助,欢迎 点赞、收藏、关注

深入理解 Java 多线程、Lambda 表达式及线程安全最佳实践的更多相关文章

  1. 《深入理解Java虚拟机:JVM高级特性与最佳实践》【PDF】下载

    <深入理解Java虚拟机:JVM高级特性与最佳实践>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062566 内容简介 作为一位 ...

  2. 读书笔记-《深入理解Java虚拟机:JVM高级特性与最佳实践》

    目录 概述 第一章: 走进Java 第二章: Java内存区域与内存溢出异常 第三章: 垃圾收集器与内存分配策略 第四章: 虚拟机性能监控与故障处理 第五章: 调优案例分析与实战 第六章: 类文件结构 ...

  3. Java 多线程 -- lambda 表达式推导

    jdk 8 开始 java 引入了lambda 表达式. lambda适用场景: 1.接口或父类 2.接口或父类只有一个方法 我们从多线程写法来推导一下: 1.外部类写法: package com.x ...

  4. 2018.4.23 《深入理解Java虚拟机:JVM高级特性与最佳实践》笔记

    一.Java内存区域与内存溢出 1.程序计数器是一块较小的内存空间,它可看作是当前线程所执行的字节码的行号指示器.字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令.各条线程 ...

  5. 《深入理解Java虚拟机:JVM高级特性与最佳实践》读书笔记

    第一部分 走进Java 一.走进Java 1.概述 java广泛应用于嵌入式系统.移动终端.企业服务器.大型机等各种场合,摆脱了硬件平台的束缚,实现了“一次编写,到处运行”的理想 2.java技术体系 ...

  6. 《深入理解Java虚拟机:JVM高级属性与最佳实践》读书笔记(更新中)

    第一章:走进Java 概述 Java技术体系 Java发展史 Java虚拟机发展史 1996年 JDK1.0,出现Sun Classic VM HotSpot VM, 它是 Sun JDK 和 Ope ...

  7. 深入理解Java虚拟机:JVM高级特性与最佳实践

    第一部分走近Java第1章走近Java21.1概述21.2Java技术体系31.3Java发展史51.4Java虚拟机发展史91.4.1SunClassicExactVM91.4.2SunHotSpo ...

  8. 深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)请自取

    最近在读,附上网盘链接 复制这段内容后打开百度网盘手机App,操作更方便哦 链接:https://pan.baidu.com/s/1U6yFeZxz9uD6sSiu-Br06g 提取码:3Wt4

  9. java的线程、创建线程的 3 种方式、静态代理模式、Lambda表达式简化线程

    0.介绍 线程:多个任务同时进行,看似多任务同时进行,但实际上一个时间点上我们大脑还是只在做一件事情.程序也是如此,除非多核cpu,不然一个cpu里,在一个时间点里还是只在做一件事,不过速度很快的切换 ...

  10. Java 8 Lambda表达式学习和理解

    Java 8 Lambda表达式和理解 说明:部分资料来源于网络 时间:20190704 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性.Lambda 允许把函数作为一 ...

随机推荐

  1. 【ACM专项练习#02】输入整行字符串、输入值到vector、取输入整数的每一位

    输入整行字符串 平均绩点 题目描述 每门课的成绩分为A.B.C.D.F五个等级,为了计算平均绩点,规定A.B.C.D.F分别代表4分.3分.2分.1分.0分. 输入 有多组测试样例.每组输入数据占一行 ...

  2. 04、RS232 协议介绍

    从之前的学习,我们知道了 SECS-I 使用的 RS232 来进行数据的传输,那我们也初略的了解下 RS232. 这一篇不用看也可以. 这是最低的协议层.它定义了设备上的物理接口.它是基于RS-232 ...

  3. 【Azure API 管理】APIM Self-Host Gateway 自建本地环境中的网关数量超过10个且它们的出口IP为同一个时出现的429错误

    问题描述 Azure API Management服务支持使用自建网关来实现API服务,这样APIM的所有请求都可以走在自管理的企业内网中.流量都更加安全.当根据官网文档搭建后,如果在本地环境中部署超 ...

  4. 【Azure 应用服务】Azure Function (PowerShell) 执行时报错 "out of memory"

    问题描述 在Azure Function App服务中,创建一个PowerShell脚本的函数,遇见了OOM(Out Of Memory)的异常报错: 2022-01-10T07:44:37 Welc ...

  5. pod常见的非故障及故障状态解析

    在Kubernetes中,Pod的状态可以反映其当前的生命周期状态.是否正常运行或遇到了某些状况.以下是一些Pod常见的非故障状态: Running:这是Pod最常见的非故障状态,表示Pod已经成功调 ...

  6. crc16校验C语言源码实例解析

    一 概念: 循环冗余码校验英文名称为Cyclical Redundancy Check,简称CRC.它是利用除法及余数的原理来作错误侦测(Error Detecting)的.实际应用时,发送装置计算出 ...

  7. python3 Crypto模块实例解析

    一 模块简介 1.简介 python的Crypto模块是安全hash函数(例如SHA256 和RIPEMD160)以及各种主流的加解密算法的((AES, DES, RSA, ElGamal等)的集合. ...

  8. day18--Java集合01

    Java集合01 1.什么是集合? 前面我们保存数据使用的是数组,数组有不足的地方,我们来分析一下: 长度开始时必须指定,而且一但指定不能更改 保存的必须是同一类型的元素 使用数组进行增加/删除元素的 ...

  9. uniapp使用uview报错Cannot find module ‘@/uni_modules/uview-ui/components

    参考:https://github.com/umicro/uView 记录使用uniapp报的错 注意uview目前只支持vue2 按照教程引入uview,然后执行的时候还是会报Cannot find ...

  10. 汽车VR虚拟仿真技术如何加速自动驾驶的发展?

    虚拟现实和虚拟仿真将带领自动驾驶汽车从汽车研发.体验.展厅.销售等各个环节迈入全新时代.2019 年,全球增强现实和虚拟现实市场为168 亿美元,到 2023 年,该市场的未来增长预计将超过 1600 ...