Java 線程 線程使程式能夠通過同時執行多個任務而更有效地運行。 線程可用於在不中斷主程式的情況下在後臺執行複雜的任務。 創建線程 有兩種創建線程的方式。 擴展Thread類 可以通過擴展Thread類並覆蓋其run()方法來創建線程: public class MyThread extends ...
Java 線程
線程使程式能夠通過同時執行多個任務而更有效地運行。
線程可用於在不中斷主程式的情況下在後臺執行複雜的任務。
創建線程
有兩種創建線程的方式。
- 擴展Thread類
可以通過擴展Thread類並覆蓋其run()方法來創建線程:
public class MyThread extends Thread {
public void run() {
System.out.println("This code is running in a thread");
}
}
- 實現Runnable介面
另一種創建線程的方式是實現Runnable介面:
public class MyRunnable implements Runnable {
public void run() {
System.out.println("This code is running in a thread");
}
}
運行線程
- 擴展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");
}
}
- 實現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
,關註後即可獲取最新文章推送
看完如果覺得有幫助,歡迎 點贊、收藏、關註