Java 教程

Java 控制语句

面向对象编程

Java 内置类

Java 文件处理

Java 错误与异常

Java 多线程

Java 同步

Java 网络

Java 集合

Java 接口

Java 数据结构

Java 集合算法

高级 Java

Java 杂项

Java API 和框架

Java 类参考

Java 有用资源

Java - 多线程



Java 是一种多线程编程语言,这意味着我们可以使用 Java 开发多线程程序。多线程程序包含两个或多个可以并发运行的部分,并且每个部分可以同时处理不同的任务,从而充分利用可用资源,尤其是在您的计算机有多个CPU时。

根据定义,多任务处理是指多个进程共享 CPU 等公共处理资源。多线程将多任务处理的概念扩展到应用程序中,在应用程序中,您可以将单个应用程序内的特定操作细分为单独的线程。每个线程都可以并行运行。操作系统不仅在不同的应用程序之间分配处理时间,而且在应用程序内的每个线程之间分配处理时间。

Java 多线程

多线程使您能够以一种方式编写代码,在该代码中,多个活动可以在同一程序中并发进行。为了实现多线程(或编写多线程代码),您需要java.lang.Thread 类

Java 多线程中线程的生命周期

线程在其生命周期中会经历各个阶段。例如,线程诞生、启动、运行,然后死亡。下图显示了线程的完整生命周期。

Java Thread Life Cycle

以下是生命周期的阶段:

  • 新建 - 新线程从新建状态开始其生命周期。它保持在此状态,直到程序启动线程。它也称为新生线程

  • 可运行 - 新生线程启动后,线程变为可运行状态。处于此状态的线程被认为正在执行其任务。

  • 等待 - 有时,线程在等待另一个线程执行任务时会过渡到等待状态。线程仅在另一个线程发出信号让等待线程继续执行时才返回到可运行状态。

  • 计时等待 - 可运行线程可以在指定的时间间隔内进入计时等待状态。处于此状态的线程在该时间间隔到期或其等待的事件发生时返回到可运行状态。

  • 终止(死亡) - 可运行线程在完成其任务或以其他方式终止时进入终止状态。

线程优先级

每个 Java 线程都有一个优先级,它可以帮助操作系统确定线程的调度顺序。

Java 线程优先级范围在 MIN_PRIORITY(常量 1)和 MAX_PRIORITY(常量 10)之间。默认情况下,每个线程都分配了 NORM_PRIORITY(常量 5)的优先级。

优先级较高的线程对程序更重要,应在优先级较低的线程之前分配处理器时间。但是,线程优先级不能保证线程执行的顺序,并且在很大程度上取决于平台。

通过实现 Runnable 接口创建线程

如果您的类旨在作为线程执行,那么您可以通过实现Runnable接口来实现。您需要遵循三个基本步骤:

步骤 1:实现 run() 方法

第一步,您需要实现Runnable接口提供的 run() 方法。此方法为线程提供了一个入口点,您将在其中放置完整的业务逻辑。以下是 run() 方法的简单语法:

public void run( )

步骤 2:实例化 Thread 对象

第二步,您将使用以下构造函数实例化Thread对象:

Thread(Runnable threadObj, String threadName);

其中,threadObj是实现Runnable接口的类的实例,threadName是赋予新线程的名称。

步骤 3:使用 start() 方法调用线程

创建 Thread 对象后,您可以通过调用start()方法启动它,该方法会执行对 run( ) 方法的调用。以下是 start() 方法的简单语法:

void start();

示例:通过实现 Runnable 接口创建线程

这是一个创建新线程并开始运行它的示例:

class RunnableDemo implements Runnable {
   private Thread t;
   private String threadName;
   
   RunnableDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      try {
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            // Let the thread sleep for a while.
            Thread.sleep(50);
         }
      } catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  threadName );
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}

public class TestThread {

   public static void main(String args[]) {
      RunnableDemo R1 = new RunnableDemo( "Thread-1");
      R1.start();
      
      RunnableDemo R2 = new RunnableDemo( "Thread-2");
      R2.start();
   }   
}

输出

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

通过扩展 Thread 类创建线程

创建线程的第二种方法是创建一个扩展Thread类的新的类,使用以下两个简单的步骤。这种方法在处理使用Thread类中可用方法创建的多个线程时提供了更大的灵活性。

步骤 1:重写 run() 方法

您需要重写Thread类中可用的run( )方法。此方法为线程提供了一个入口点,您将在其中放置完整的业务逻辑。以下是run()方法的简单语法:

public void run( )

步骤 2:使用 start() 方法调用线程

创建Thread对象后,您可以通过调用start()方法启动它,该方法会调用run( )方法。以下是start()方法的简单语法:

void start( );

示例:通过扩展Thread类创建线程

以下是前面程序重写为扩展Thread的示例:

class ThreadDemo extends Thread {
   private Thread t;
   private String threadName;
   
   ThreadDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      try {
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            // Let the thread sleep for a while.
            Thread.sleep(50);
         }
      } catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  threadName );
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}

public class TestThread {

   public static void main(String args[]) {
      ThreadDemo T1 = new ThreadDemo( "Thread-1");
      T1.start();
      
      ThreadDemo T2 = new ThreadDemo( "Thread-2");
      T2.start();
   }   
}

输出

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

线程方法

以下是Thread类中可用的一些重要方法列表。

序号 方法及描述
1

public void start()

在单独的执行路径中启动线程,然后在此Thread对象上调用run()方法。

2

public void run()

如果此Thread对象是使用单独的Runnable目标实例化的,则在此Runnable对象上调用run()方法。

3

public final void setName(String name)

更改Thread对象的名称。还有一个getName()方法用于检索名称。

4

public final void setPriority(int priority)

设置此Thread对象的优先级。可能的值介于1到10之间。

5

public final void setDaemon(boolean on)

值为true表示此线程为守护线程。

6

public final void join(long millisec)

当前线程在此第二个线程上调用此方法,导致当前线程阻塞,直到第二个线程终止或指定的毫秒数过去。

7

public void interrupt()

中断此线程,使其继续执行(如果由于任何原因而被阻塞)。

8

public final boolean isAlive()

如果线程处于活动状态,则返回true,即线程启动后但在运行完成之前。

之前的方法是在特定的Thread对象上调用的。Thread类中的以下方法是静态的。调用其中一个静态方法会在当前正在运行的线程上执行操作。

序号 方法及描述
1

public static void yield()

导致当前正在运行的线程让出给任何其他具有相同优先级且正在等待调度的线程。

2

public static void sleep(long millisec)

导致当前正在运行的线程至少阻塞指定毫秒数。

3

public static boolean holdsLock(Object x)

如果当前线程持有给定Object上的锁,则返回true。

4

public static Thread currentThread()

返回对当前正在运行的线程的引用,该线程是调用此方法的线程。

5

public static void dumpStack()

打印当前正在运行的线程的堆栈跟踪,这在调试多线程应用程序时很有用。

示例

以下ThreadClassDemo程序演示了Thread类的一些方法。考虑一个实现RunnableDisplayMessage类:

// File Name : DisplayMessage.java
// Create a thread to implement Runnable

public class DisplayMessage implements Runnable {
   private String message;
   
   public DisplayMessage(String message) {
      this.message = message;
   }
   
   public void run() {
      while(true) {
         System.out.println(message);
      }
   }
}

以下是另一个扩展Thread类的类:

// File Name : GuessANumber.java
// Create a thread to extentd Thread

public class GuessANumber extends Thread {
   private int number;
   public GuessANumber(int number) {
      this.number = number;
   }
   
   public void run() {
      int counter = 0;
      int guess = 0;
      do {
         guess = (int) (Math.random() * 100 + 1);
         System.out.println(this.getName() + " guesses " + guess);
         counter++;
      } while(guess != number);
      System.out.println("** Correct!" + this.getName() + "in" + counter + "guesses.**");
   }
}

以下是主程序,它使用了上面定义的类:

// File Name : ThreadClassDemo.java
public class ThreadClassDemo {

   public static void main(String [] args) {
      Runnable hello = new DisplayMessage("Hello");
      Thread thread1 = new Thread(hello);
      thread1.setDaemon(true);
      thread1.setName("hello");
      System.out.println("Starting hello thread...");
      thread1.start();
      
      Runnable bye = new DisplayMessage("Goodbye");
      Thread thread2 = new Thread(bye);
      thread2.setPriority(Thread.MIN_PRIORITY);
      thread2.setDaemon(true);
      System.out.println("Starting goodbye thread...");
      thread2.start();

      System.out.println("Starting thread3...");
      Thread thread3 = new GuessANumber(27);
      thread3.start();
      try {
         thread3.join();
      } catch (InterruptedException e) {
         System.out.println("Thread interrupted.");
      }
      System.out.println("Starting thread4...");
      Thread thread4 = new GuessANumber(75);
      
      thread4.start();
      System.out.println("main() is ending...");
   }
}
class DisplayMessage implements Runnable {
   private String message;
   
   public DisplayMessage(String message) {
      this.message = message;
   }
   
   public void run() {
      while(true) {
         System.out.println(message);
      }
   }
}
class GuessANumber extends Thread {
   private int number;
   public GuessANumber(int number) {
      this.number = number;
   }
   
   public void run() {
      int counter = 0;
      int guess = 0;
      do {
         guess = (int) (Math.random() * 100 + 1);
         System.out.println(this.getName() + " guesses " + guess);
         counter++;
      } while(guess != number);
      System.out.println("** Correct!" + this.getName() + "in" + counter + "guesses.**");
   }
}

输出

Starting hello thread...
Starting goodbye thread...
Hello
Hello
Hello
Hello
Hello
Hello
Goodbye
Goodbye
Goodbye
Goodbye
Goodbye
.......

主要的Java多线程概念

在Java中进行多线程编程时,您需要掌握以下概念:

广告