全干工程师

Java-Logo

Java多线程并发是什么

您可能对多任务处理并不陌生,它是指一个人试图同时执行两项或多项任务。虽然人并不擅长多任务处理,但事实证明,计算机却可以!计算机系统配备多个处理器或具有多个执行内核的处理器已变得越来越普遍,这大大增强了系统并发执行进程和线程的能力。

即使在只有一个处理器或执行核心的简单系统中,也可以实现这一过程。在软件术语中,同时执行多个任务称为并发。并发性也可定义为并行运行多个程序或程序的多个部分的能力。

您一定很高兴知道,Java 平台从设计之初就支持并发编程,Java 编程语言和 Java 类库都支持基本的并发功能。自 5.0 版起,Java 平台还包含了高级并发 API。我们将在本编程教程中进一步讨论这一概念。

进程与Java线程

在并发编程中,有两种基本的执行类型:进程和线程。在Java中,并发编程主要通过线程来实现。不过,进程也发挥着重要作用。

通常情况下,计算机系统在任何时刻都会有许多活跃的进程和线程在运行,尤其是在多处理器的计算机系统已成为常态的情况下;更多的处理器大大提高了系统并发执行进程和线程的能力。即使在只有一个内核的系统中,在任何特定时刻都只能有一个线程在执行,也可以通过操作系统的时间切片功能共享进程和线程。

什么是多线程中的进程?

进程有一个自足的执行环境。因此,进程通常拥有一套完整、私有的运行时资源,如内存空间。进程与程序或应用程序之间并不是一对一的关系,因为通常情况下,一个应用程序可能由一组合作的进程组成。进程之间的通信是通过进程间通信(IPC)资源实现的,其中包括管道和套接字。IPC 可用于同一系统甚至不同系统进程之间的通信。

Java虚拟机的大多数实现都以单个进程的形式运行,但Java应用程序可以使用ProcessBuilder对象创建其他进程。

什么是多线程中的线程?

线程通常被称为轻量级进程,与普通进程类似,都提供了一个执行环境。不过,创建一个新线程所需的资源比创建一个新进程要少。

线程存在于进程中,这意味着每个进程至少有一个线程。进程内的所有线程共享其资源,包括内存和打开的文件。因此,线程具有很高的效率,但如果处理不慎,也会产生问题。

多线程执行是Java平台的一项基本功能,使其成为并发编程的理想选择。每个应用程序开始时都只有一个线程,称为主线程。在此基础上,程序员可以创建额外的线程,我们将在下一节中看到这一点。

在Java中定义和启动线程

Java中,每个线程都与Thread类的一个实例相关联。因此,应用程序可以通过创建一个Thread实例,然后提供将在该线程中运行的代码,来产生一个新线程。实现这一点有两种方法:

  1. 提供一个 Runnable 对象

Runnable接口定义了一个方法run,该方法包含在线程中执行的代码。如下例所示,Runnable对象被传递给线程构造函数:

public class HelloWorldRunnableExample implements Runnable {
    public void run() {
        System.out.println("Hello from a thread!");
    }
    public static void main(String args[]) {
        (new Thread(new HelloWorldRunnableExample())).start();
    }
}
  1. Thread子类

Thread类本身实现了Runnable,但它的run方法什么也不做。应用程序可以子类化Thread,提供自己的run实现,如下面的代码示例所示:

public class HelloWorldThreadExample extends Thread {
    public void run() {
        System.out.println("Hello from a thread!");
    }
    public static void main(String args[]) {
        (new HelloWorldThreadExample()).start();
    }
}

在这两种情况下,程序都会调用**Thread.start()**来启动新线程。

如何暂停线程执行

开发人员可以使用静态**Thread.sleep()**方法在指定时间内暂停线程的执行。这是一种简单的方法,可以为应用程序的其他线程甚至可能在同一设备上运行的其他应用程序提供更多的处理器时间。**sleep()**方法的第二个用途是控制应用程序的步调,如下图所示:

public class SleepExample {
  public static void main(String args[]) throws InterruptedException {
    String lyrics[] = {
      "Signals transmitted",
      "Message received",
      "Reaction making impact",
      "Invisibly"
    };

    for (int i = 0; i < lyrics.length; i++) {
      // 2秒后打印消息
      Thread.sleep(2000);
      System.out.println(lyrics[i]);
    }
  }
}

请注意,**main()**方法声明会抛出InterruptedException。这是当另一个线程在睡眠过程中中断当前线程时,睡眠抛出的异常。

总结

本教程介绍了使用Java进行并发编程的一些基础知识,包括如何创建线程并暂时中止其执行。在多线程环境中工作时,请注意如果一个线程试图读取共享数据,而另一个线程随后又更改了该数据,则可能会出现问题。如果多个线程试图同时访问和更改相同的数据,也可能出现问题。这两种情况都很严重,因为它们可能导致执行死锁和数据损坏。

既然您已经了解了Java并发性的基础知识,请查看我们的Java 多线程最佳实践教程。

本文章翻译于What is Concurrency in Java?

留言