ToB企服应用市场:ToB评测及商务社交产业平台

标题: 深入理解 Java 多线程、Lambda 表达式及线程安全最佳实践 [打印本页]

作者: 九天猎人    时间: 2024-5-14 07:15
标题: 深入理解 Java 多线程、Lambda 表达式及线程安全最佳实践
Java 线程

线程使程序能够通过同时实行多个任务而更有效地运行。
线程可用于在不中断主程序的情况下在后台实行复杂的任务。
创建线程

有两种创建线程的方式。
可以通过扩展Thread类并覆盖其run()方法来创建线程:
  1. public class MyThread extends Thread {
  2.   public void run() {
  3.     System.out.println("This code is running in a thread");
  4.   }
  5. }
复制代码
另一种创建线程的方式是实现Runnable接口:
  1. public class MyRunnable implements Runnable {
  2.   public void run() {
  3.     System.out.println("This code is running in a thread");
  4.   }
  5. }
复制代码
运行线程

如果类扩展Thread类,则可以通过创建类的实例并调用其start()方法来运行线程:
  1. public class Main {
  2.   public static void main(String[] args) {
  3.     MyThread myThread = new MyThread();
  4.     myThread.start();
  5.     System.out.println("This code is outside of the thread");
  6.   }
  7. }
复制代码
如果类实现了Runnable接口,则可以通过将类的实例通报给Thread对象的构造函数,然后调用线程的start()方法来运行线程:
  1. public class Main {
  2.   public static void main(String[] args) {
  3.     MyRunnable myRunnable = new MyRunnable();
  4.     Thread thread = new Thread(myRunnable);
  5.     thread.start();
  6.     System.out.println("This code is outside of the thread");
  7.   }
  8. }
复制代码
区分“扩展”和“实现”线程

主要区别在于,当一个类扩展Thread类时,无法扩展任何其他类,但通过实现Runnable接口,可以扩展另一个类,例如:
  1. class MyClass extends OtherClass implements Runnable
复制代码
并发问题

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

一个变量amount值不可预测的代码示例:
  1. public class Main extends Thread {
  2.   public static int amount = 0;
  3.   public static void main(String[] args) {
  4.     Main thread = new Main();
  5.     thread.start();
  6.     System.out.println(amount);
  7.     amount++;
  8.     System.out.println(amount);
  9.   }
  10.   public void run() {
  11.     amount++;
  12.   }
  13. }
复制代码
为避免并发问题,最好尽大概少地在线程之间共享属性。如果须要共享属性,一种大概的解决方案是在使用线程可以更改的任何属性之前,使用线程的isAlive()方法检查线程是否已完成运行。
示例

使用isAlive()防止并发问题:
  1. public class Main extends Thread {
  2.   public static int amount = 0;
  3.   public static void main(String[] args) {
  4.     Main thread = new Main();
  5.     thread.start();
  6.     // 等待线程完成
  7.     while (thread.isAlive()) {
  8.       System.out.println("Waiting...");
  9.     }
  10.     // 更新amount并打印其值
  11.     System.out.println("Main program: " + amount);
  12.     amount++;
  13.     System.out.println("Main program: " + amount);
  14.   }
  15.   public void run() {
  16.     amount++;
  17.   }
  18. }
复制代码
线程池

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

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

避免线程安全问题

Java Lambda表达式

Lambda表达式简介

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

最简单的Lambda表达式包含一个参数和一个表达式:
  1. 参数 -> 表达式
复制代码
要使用多个参数,请将它们放在括号中:
  1. (参数1, 参数2) -> 表达式
复制代码
表达式是有限制的。它们必须立即返回一个值,并且不能包含变量、赋值或if或for等语句。为了实行更复杂的操作,可以使用带有花括号的代码块。如果Lambda表达式须要返回一个值,那么代码块应该有一个return语句。
  1. (参数1, 参数2) -> { 代码块 }
复制代码
Lambda表达式的使用

Lambda表达式通常作为参数通报给函数。在以下示例中,Lambda表达式作为参数通报给ArrayList的forEach()方法,以打印列表中的每个项:
  1. import java.util.ArrayList;
  2. public class Main {
  3.   public static void main(String[] args) {
  4.     ArrayList<Integer> numbers = new ArrayList<>();
  5.     numbers.add(5);
  6.     numbers.add(9);
  7.     numbers.add(8
  8. );
  9.     numbers.add(1);
  10.     numbers.forEach((n) -> { System.out.println(n); });
  11.   }
  12. }
复制代码
Lambda表达式的存储

如果变量的类型是仅具有一个方法的接口,那么Lambda表达式可以存储在变量中。Lambda表达式应该具有与该方法相同数量的参数和相同的返回类型。Java内置了许多这类接口,如Consumer接口(在java.util包中),它被列表使用。
  1. import java.util.ArrayList;
  2. import java.util.function.Consumer;
  3. public class Main {
  4.   public static void main(String[] args) {
  5.     ArrayList<Integer> numbers = new ArrayList<>();
  6.     numbers.add(5);
  7.     numbers.add(9);
  8.     numbers.add(8);
  9.     numbers.add(1);
  10.     Consumer<Integer> method = (n) -> { System.out.println(n); };
  11.     numbers.forEach(method);
  12.   }
  13. }
复制代码
Lambda表达式作为方法参数

要在方法中使用Lambda表达式,该方法应该有一个以单一方法接口作为其类型的参数。调用接口的方法将运行Lambda表达式。
  1. interface StringFunction {
  2.   String run(String str);
  3. }
  4. public class Main {
  5.   public static void main(String[] args) {
  6.     StringFunction exclaim = (s) -> s + "!";
  7.     StringFunction ask = (s) -> s + "?";
  8.     printFormatted("Hello", exclaim);
  9.     printFormatted("Hello", ask);
  10.   }
  11.   public static void printFormatted(String str, StringFunction format) {
  12.     String result = format.run(str);
  13.     System.out.println(result);
  14.   }
  15. }
复制代码
Lambda表达式的优势

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

为了方便其他装备宁静台的小伙伴观看往期文章:
微信公众号搜索:Let us Coding,关注后即可获取最新文章推送
看完如果以为有帮助,欢迎 点赞、收藏、关注

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4