Java 线程

Java 线程

线程允许一个程序在同一时间做多件事,从而更高效地运行。

线程可以在后台执行复杂的任务,而不会中断主程序。


创建线程

创建线程有两种方法。

可以通过扩展 Thread 类并重写其 run() 方法来创建:

Extend 语法
  1. public class Main extends Thread {
  2. public void run() {
  3. System.out.println("This code is running in a thread");
  4. }
  5. }

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

Implement 语法
  1. public class Main implements Runnable {
  2. public void run() {
  3. System.out.println("This code is running in a thread");
  4. }
  5. }

运行线程

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

Extend 实例
  1. public class Main extends Thread {
  2. public static void main(String[] args) {
  3. Main thread = new Main();
  4. thread.start();
  5. System.out.println("This code is outside of the thread");
  6. }
  7. public void run() {
  8. System.out.println("This code is running in a thread");
  9. }
  10. }

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

Implement 实例
  1. public class Main implements Runnable {
  2. public static void main(String[] args) {
  3. Main obj = new Main();
  4. Thread thread = new Thread(obj);
  5. thread.start();
  6. System.out.println("This code is outside of the thread");
  7. }
  8. public void run() {
  9. System.out.println("This code is running in a thread");
  10. }
  11. }
Extend 和 Implement 线程之间的区别
主要区别在于,当一个类扩展 Thread 类时,不能扩展任何其他类,但通过实现 Runnable 接口,也可以从另一个类进行扩展,比如: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. // Wait for the thread to finish
  7. while(thread.isAlive()) {
  8. System.out.println("Waiting...");
  9. }
  10. // Update amount and print its value
  11. System.out.println("Main: " + amount);
  12. amount++;
  13. System.out.println("Main: " + amount);
  14. }
  15. public void run() {
  16. amount++;
  17. }
  18. }