亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> java

Java 多线程编程精通:高效并发编程实战指南

Java 是一门 多线程编程语言,意味着我们可以用 Java 开发多线程程序。多线程程序包含两个或更多可并发运行的部分,每部分可同时处理不同任务,从而最优利用可用资源,特别是当计算机有多个 CPU 时。

按定义,多任务是指多个进程共享 CPU 等通用处理资源。多线程将多任务的概念扩展到应用程序内部,可将单个应用中的特定操作细分为独立线程。每个线程可并行运行。操作系统不仅在不同应用间分配处理时间,也在应用内的各线程间分配。

多线程使你能以多活动在同一程序中并发进行的方式编写代码。

线程生命周期

线程在其生命周期中会经历多个阶段。例如,线程诞生、启动、运行,最终终止。下图展示了线程的完整生命周期。

Java 多线程编程精通:高效并发编程实战指南

生命周期阶段如下:

线程优先级

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

Java 线程优先级范围在 MIN_PRIORITY(常量 1)和 MAX_PRIORITY(常量 10)之间。默认每个线程优先级为 NORM_PRIORITY(常量 5)。

高优先级线程对程序更重要,应在低优先级线程前获得处理器时间。但线程优先级不能保证执行顺序,且高度依赖平台。

通过实现 Runnable 接口创建线程

若类旨在作为线程执行,可通过实现 Runnable 接口实现。需遵循三个基本步骤:

步骤 1

首先实现 Runnable 接口提供的 run() 方法。此方法为线程入口点,完整业务逻辑放在此方法中。run() 方法简单语法:

public void run()

步骤 2

其次,使用以下构造器实例化 Thread 对象:

Thread(Runnable threadObj, String threadName);

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

步骤 3

Thread 对象创建后,调用 start() 方法启动,这会执行 run() 方法调用。start() 方法简单语法:

void start();

示例

下例创建新线程并启动运行:

在线演示
class RunnableDemo implements Runnable {
    private Thread t;
    private String threadName;
    RunnableDemo(String name) {
        threadName = name;
        System.out.println("创建 " + threadName);
    }
    public void run() {
        System.out.println("运行 " + threadName);
        try {
            for(int i = 4; i > 0; i--) {
                System.out.println("线程: " + threadName + ", " + i);
                // 让线程休眠片刻
                Thread.sleep(50);
            }
        } catch (InterruptedException e) {
            System.out.println("线程 " + threadName + " 被中断。");
        }
        System.out.println("线程 " + threadName + " 退出。");
    }
    public void start() {
        System.out.println("启动 " + 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();
    }
}

输出结果如下:

输出

创建 Thread-1
启动 Thread-1
创建 Thread-2
启动 Thread-2
运行 Thread-1
线程: Thread-1, 4
运行 Thread-2
线程: Thread-2, 4
线程: Thread-1, 3
线程: Thread-2, 3
线程: Thread-1, 2
线程: Thread-2, 2
线程: Thread-1, 1
线程: Thread-2, 1
线程 Thread-1 退出。
线程 Thread-2 退出。

通过继承 Thread 类创建线程

创建线程的第二种方式是创建新类继承 Thread 类,仅需两步。此方式利用 Thread 类可用方法提供更灵活的多线程处理。

步骤 1

需重写 Thread 类中的 run() 方法。此方法为线程入口点,完整业务逻辑放在此方法中。run() 方法简单语法:

public void run()

步骤 2

Thread 对象创建后,调用 start() 方法启动,执行 run() 方法调用。start() 方法简单语法:

void start();

示例

下面是前面程序改写为继承 Thread 类的版本:

在线演示
class ThreadDemo extends Thread {
    private Thread t;
    private String threadName;
    ThreadDemo(String name) {
        threadName = name;
        System.out.println("创建 " + threadName);
    }
    public void run() {
        System.out.println("运行 " + threadName);
        try {
            for(int i = 4; i > 0; i--) {
                System.out.println("线程: " + threadName + ", " + i);
                Thread.sleep(50);
            }
        } catch (InterruptedException e) {
            System.out.println("线程 " + threadName + " 被中断。");
        }
        System.out.println("线程 " + threadName + " 退出。");
    }
    public void start() {
        System.out.println("启动 " + 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();
    }
}

输出结果如下:

输出

创建 Thread-1
启动 Thread-1
创建 Thread-2
启动 Thread-2
运行 Thread-1
线程: Thread-1, 4
运行 Thread-2
线程: Thread-2, 4
线程: Thread-1, 3
线程: Thread-2, 3
线程: Thread-1, 2
线程: Thread-2, 2
线程: Thread-1, 1
线程: Thread-2, 1
线程 Thread-1 退出。
线程 Thread-2 退出。

Thread 类常用方法

以下是 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 时将此 Thread 标记为守护线程。

6

public final void join(long millisec)

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

7

public void interrupt()

中断此线程,使其在因任何原因阻塞时继续执行。

8

public final boolean isAlive()

若线程存活则返回 true,即线程启动后但在运行完成前的任何时间。

上述方法在特定 Thread 对象上调用。Thread 类中以下方法为静态方法。调用静态方法时对当前运行线程执行操作。

序号方法及描述
1

public static void yield()

使当前运行线程让出 CPU,调度同优先级的其他等待线程。

2

public static void sleep(long millisec)

使当前运行线程阻塞至少指定毫秒数。

3

public static boolean holdsLock(Object x)

若当前线程持有给定对象的锁则返回 true。

4

public static Thread currentThread()

返回对当前运行线程的引用,即调用此方法的线程。

5

public static void dumpStack()

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

示例

下面的 ThreadClassDemo 程序演示 Thread 类的部分方法。考虑实现 Runnable 的 DisplayMessage 类:

// 文件名:DisplayMessage.java
// 创建实现 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 类的类:

// 文件名:GuessANumber.java
// 创建继承 Thread 的线程
public class GuessANumber extends Thread {
    private int number;
    public GuessANumber(int number) { this.number = number; }
    public void run() {
        int counter = 0, guess = 0;
        do {
            guess = (int) (Math.random() * 100 + 1);
            System.out.println(this.getName() + " 猜测 " + guess);
            counter++;
        } while(guess != number);
        System.out.println("** 正确!" + this.getName() + "在" + counter + "次猜测后。**");
    }
}

使用上述类的主程序:

// 文件名: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("启动 hello 线程...");
        thread1.start();

        Runnable bye = new DisplayMessage("Goodbye");
        Thread thread2 = new Thread(bye);
        thread2.setPriority(Thread.MIN_PRIORITY);
        thread2.setDaemon(true);
        System.out.println("启动 goodbye 线程...");
        thread2.start();

        System.out.println("启动 thread3...");
        Thread thread3 = new GuessANumber(27);
        thread3.start();
        try { thread3.join(); } catch (InterruptedException e) { System.out.println("线程中断。"); }

        System.out.println("启动 thread4...");
        Thread thread4 = new GuessANumber(75);
        thread4.start();
        System.out.println("main() 结束...");
    }
}

运行结果(每次运行结果不同):

输出

启动 hello 线程...
启动 goodbye 线程...
Hello
Hello
Hello
Hello
Hello
Hello
Goodbye
Goodbye
Goodbye
Goodbye
Goodbye
.......

Java 多线程核心概念

进行 Java 多线程编程时,需熟练掌握以下概念:

java

  1. 精通 C++ 多线程编程:高效并发开发实战
  2. C# 多线程编程精通:提升性能与效率的核心技术
  3. 精通 Java 运算符:类型、语法与实战示例
  4. Java 注释:类型、用法与最佳实践
  5. 精通 Java 增强 for 循环:语法、示例与最佳实践
  6. 精通 Java 字符串:创建、方法与最佳实践
  7. 精通 Java 接口:概念、实现与最佳实践
  8. 精通 Java 匿名内部类:定义、语法与实战示例
  9. 精通 Java Try-With-Resources:自动资源管理详解
  10. Java 注解详解:类型、放置位置与实战示例
  11. Java 断言实战指南:尽早发现 Bug 与保障代码可靠性
  12. 深入理解 Java Vector:用法、特性及与 ArrayList 的对比