Java 线程示例

歡迎來到Java執行緒範例。處理和執行緒是兩個基本的執行單位。並行程式設計更關注於Java執行緒。

處理

A process is a self contained execution environment and it can be seen as a program or application. However a program itself contains multiple processes inside it. Java runtime environment runs as a single process which contains different classes and programs as processes.

執行緒

執行緒可以被稱為輕量級處理。執行緒需要較少的資源來建立並存在於處理中,執行緒共享處理的資源。

Java執行緒範例

每個Java應用程序至少有一個線程-主線程。儘管還有許多其他Java線程在後台運行,例如內存管理、系統管理、信號處理等,但從應用程序的角度來看,主線程是第一個Java線程,我們可以從它創建多個線程。多線程指的是兩個或多個線程在一個程序中同時執行。計算機的單核處理器一次只能執行一個線程,時間片是操作系統的一個特性,用於在不同的進程和線程之間共享處理器時間。

Java線程的好處

  1. 與進程相比,Java線程輕量級,創建一個線程需要更少的時間和資源。
  2. 線程共享其父進程的數據和代碼。
  3. 線程之間的上下文切換通常比進程之間的切換成本更低。
  4. 與進程通信相比,線程間的通信相對容易。

Java提供了兩種創建線程的方法。

  1. 實現java.lang.Runnable接口。
  2. 擴展java.lang.Thread類。

Java 线程示例 – 实现 Runnable 接口

为了使一个类可运行,我们可以实现 java.lang.Runnable 接口,并在 public void run() 方法中提供实现。要将这个类用作线程,我们需要创建一个 Thread 对象,通过传递该可运行类的对象来调用 start() 方法以在单独的线程中执行 run() 方法。以下是一个通过实现 Runnable 接口的 Java 线程示例。

package com.journaldev.threads;

public class HeavyWorkRunnable implements Runnable {

    @Override
    public void run() {
        System.out.println("Doing heavy processing - START "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            // 获取数据库连接,从数据库中删除未使用的数据
            doDBProcessing();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Doing heavy processing - END "+Thread.currentThread().getName());
    }

    private void doDBProcessing() throws InterruptedException {
        Thread.sleep(5000);
    }

}

Java 线程示例 – 继承 Thread 类

我们可以扩展 java.lang.Thread 类来创建自己的 Java 线程类,并重写 run() 方法。然后,我们可以创建该类的对象,并调用 start() 方法来执行我们自定义的 Java 线程类的 run 方法。以下是一个简单的 Java 线程示例,演示如何扩展 Thread 类。

package com.journaldev.threads;

public class MyThread extends Thread {

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println("MyThread - START "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            // 获取数据库连接,从数据库中删除未使用的数据
            doDBProcessing();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("MyThread - END "+Thread.currentThread().getName());
    }

    private void doDBProcessing() throws InterruptedException {
        Thread.sleep(5000);
    }
    
}

以下是一个测试程序,演示如何创建一个 Java 线程并执行它。

package com.journaldev.threads;

public class ThreadRunExample {

    public static void main(String[] args){
        Thread t1 = new Thread(new HeavyWorkRunnable(), "t1");
        Thread t2 = new Thread(new HeavyWorkRunnable(), "t2");
        System.out.println("Starting Runnable threads");
        t1.start();
        t2.start();
        System.out.println("Runnable Threads has been started");
        Thread t3 = new MyThread("t3");
        Thread t4 = new MyThread("t4");
        System.out.println("Starting MyThreads");
        t3.start();
        t4.start();
        System.out.println("MyThreads has been started");
        
    }
}

上述 Java 线程示例程序的输出结果为:

Starting Runnable threads
Runnable Threads has been started
Doing heavy processing - START t1
Doing heavy processing - START t2
Starting MyThreads
MyThread - START Thread-0
MyThreads has been started
MyThread - START Thread-1
Doing heavy processing - END t2
MyThread - END Thread-1
MyThread - END Thread-0
Doing heavy processing - END t1

一旦我們開始任何線程,它的執行取決於操作系統對時間片的實現,我們無法控制它們的執行。然而,我們可以設置線程的優先級,但即使如此,也不能保證優先級較高的線程會先執行。多次運行上述程序,你會發現線程啟動和結束沒有任何模式。

Runnable vs Thread

如果你的類提供的功能不僅僅是作為線程運行,你應該實現Runnable接口以提供運行它作為線程的方式。如果你的類的唯一目標是作為線程運行,你可以擴展Thread類。實現Runnable是首選的,因為Java支持實現多個接口。如果你擴展Thread類,就不能再擴展其他類。

提示:正如你已經注意到的,線程不返回任何值,但如果我們希望線程進行一些處理,然後將結果返回給客戶端程序,請查看我們的Java Callable Future

更新:從Java 8開始,Runnable是一個函數式接口,我們可以使用Lambda表達式提供其實現,而不是使用匿名類。有關更多詳細信息,請查看Java 8 函數式接口

Source:
https://www.digitalocean.com/community/tutorials/java-thread-example