# java 多线程

> 原文： [https://beginnersbook.com/2013/03/multithreading-in-java/](https://beginnersbook.com/2013/03/multithreading-in-java/)

在我们讨论**多线程**之前，让我们讨论一下线程。线程是进程的轻量级最小部分，可以与同一进程的其他部分（其他线程）同时运行。线程是独立的，因为它们都有单独的执行路径，这是在一个线程中发生异常的原因，它不会影响其他线程的执行。进程的所有线程共享公共内存。 **同时执行多个线程的过程称为多线程。**

让我们总结讨论点：

1.  多线程的主要目的是同时执行程序的两个或多个部分，以最大限度地利用 CPU 时间。多线程程序包含两个或多个可以并发运行的部分。程序的每个这样的部分都称为线程。

2.  线程是轻量级子进程，它们共享公共内存空间。在多线程环境中，受益于多线程的程序利用最大 CPU 时间，以便将空闲时间保持在最小。

3.  线程可以处于以下状态之一：
`NEW` - 尚未启动的线程处于此状态。
`RUNNABLE` - 在 Java 虚拟机中执行的线程处于此状态。
`BLOCKED` - 等待监视器锁定被阻塞的线程处于此状态。
`WAITING` - 一个无限期等待另一个线程执行特定操作的线程处于此状态。
`TIMED_WAITING` - 正在等待另一个线程执行最多指定等待时间的操作的线程处于此状态。
`TERMINATED` - 已退出的线程处于此状态。
线程在给定时间点只能处于一种状态。

**在此链接中了解有关线程状态的更多信息**：[线程的生命周期](https://beginnersbook.com/2013/03/thread-life-cycle-in-java/)

## 多任务与多线程与多处理与并行处理

如果您是 java 新手，您可能会对这些术语感到困惑，因为在我们讨论多线程时它们会被频繁使用。我们简要地谈谈它们。

**多任务处理：**能够同时执行多个任务称为多任务处理。

**多线程：**我们已经讨论过了。这是一个同时执行多个线程的过程。多线程也称为基于线程的多任务处理。

**多处理：**它与多任务处理相同，但在多处理中涉及多个 CPU。另一方面，一个 CPU 涉及多任务处理。

**并行处理：**它指的是在单个计算机系统中使用多个 CPU。

## 用 Java 创建一个线程

在 Java 中创建线程有两种方法：

1）通过扩展`Thread`类。

2）通过实现`Runnable`接口。

在开始创建线程的程序（代码）之前，让我们看一下`Thread`类的这些方法。我们在下面的示例中使用了很少的这些方法。

*   `getName()`：用于获取线程的名称
*   `getPriority()`：获取线程的优先级
*   `isAlive()`：确定线程是否仍在运行
*   `join()`：等待线程终止
*   `run()`：线程的入口点
*   `sleep()`：暂停线程一段时间
*   `start()`：通过调用`run()`方法启动一个线程

### 方法 1：通过扩展`Thread`类创建线程

**例 1：**

```java
class MultithreadingDemo extends Thread{  
  public void run(){  
    System.out.println("My thread is in running state.");  
  }   
  public static void main(String args[]){  
     MultithreadingDemo obj=new MultithreadingDemo();   
     obj.start();  
  }  
}
```

**输出：**

```java
My thread is in running state.
```

**例 2：**

```java
class Count extends Thread
{
   Count()
   {
     super("my extending thread");
     System.out.println("my thread created" + this);
     start();
   }
   public void run()
   {
     try
     {
        for (int i=0 ;i<10;i++)
        {
           System.out.println("Printing the count " + i);
           Thread.sleep(1000);
        }
     }
     catch(InterruptedException e)
     {
        System.out.println("my thread interrupted");
     }
     System.out.println("My thread run is over" );
   }
}
class ExtendingExample
{
   public static void main(String args[])
   {
      Count cnt = new Count();
      try
      {
         while(cnt.isAlive())
         {
           System.out.println("Main thread will be alive till the child thread is live");
           Thread.sleep(1500);
         }
      }
      catch(InterruptedException e)
      {
        System.out.println("Main thread interrupted");
      }
      System.out.println("Main thread's run is over" );
   }
}
```

**输出：**

```java
my thread createdThread[my runnable thread,5,main]
Main thread will be alive till the child thread is live
Printing the count 0
Printing the count 1
Main thread will be alive till the child thread is live
Printing the count 2
Main thread will be alive till the child thread is live
Printing the count 3
Printing the count 4
Main thread will be alive till the child thread is live
Printing the count 5
Main thread will be alive till the child thread is live
Printing the count 6
Printing the count 7
Main thread will be alive till the child thread is live
Printing the count 8
Main thread will be alive till the child thread is live
Printing the count 9
mythread run is over
Main thread run is over
```

### 方法 2：通过实现`Runnable`接口创建线程

**一个简单的例子**

```java
class MultithreadingDemo implements Runnable{  
  public void run(){  
    System.out.println("My thread is in running state.");  
  }   
  public static void main(String args[]){  
     MultithreadingDemo obj=new MultithreadingDemo();  
     Thread tobj =new Thread(obj);  
     tobj.start();  
 }  
}
```

**输出：**

```java
My thread is in running state.
```

**示例程序 2：**

观察该程序的输出并尝试了解该程序中发生的情况。如果你已经理解了每个线程方法的用法，那么你应该不会遇到任何问题，理解这个例子。

```java
class Count implements Runnable
{
   Thread mythread ;
   Count()
   { 
      mythread = new Thread(this, "my runnable thread");
      System.out.println("my thread created" + mythread);
      mythread.start();
   }
   public void run()
   {
      try
      {
        for (int i=0 ;i<10;i++)
        {
          System.out.println("Printing the count " + i);
          Thread.sleep(1000);
        }
     }
     catch(InterruptedException e)
     {
        System.out.println("my thread interrupted");
     }
     System.out.println("mythread run is over" );
   }
}
class RunnableExample
{
    public static void main(String args[])
    {
       Count cnt = new Count();
       try
       {
          while(cnt.mythread.isAlive())
          {
            System.out.println("Main thread will be alive till the child thread is live"); 
            Thread.sleep(1500);
          }
       }
       catch(InterruptedException e)
       {
          System.out.println("Main thread interrupted");
       }
       System.out.println("Main thread run is over" );
    }
}
```

**输出：**

```java
my thread createdThread[my runnable thread,5,main]
Main thread will be alive till the child thread is live
Printing the count 0
Printing the count 1
Main thread will be alive till the child thread is live
Printing the count 2
Main thread will be alive till the child thread is live
Printing the count 3
Printing the count 4
Main thread will be alive till the child thread is live
Printing the count 5
Main thread will be alive till the child thread is live
Printing the count 6
Printing the count 7
Main thread will be alive till the child thread is live
Printing the count 8
Main thread will be alive till the child thread is live
Printing the count 9
mythread run is over
Main thread run is over
```

## 线程优先级

*   线程优先级是整数，它决定了如何相对于其他线程处理一个线程。
*   线程优先级决定何时从一个正在运行的线程切换到另一个线程，该进程称为上下文切换
*   线程可以自动释放控制，并且准备运行的最高优先级线程被赋予 CPU。
*   无论优先级较低的线程正在做什么，线程都可以被更高优先级的线程抢占。每当一个更高优先级的线程想要运行它。
*   要设置线程的优先级`setPriority()`方法，这是类`Thread`类的方法。
*   我们可以使用`MIN_PRIORITY`，`NORM_PRIORITY`或`MAX_PRIORITY`代替以整数定义优先级。

## 方法：`isAlive()`和`join()`

*   在所有实际情况中，主线程应该最后完成其他从主线程产生的其他线程也将完成。
*   要知道线程是否已完成，我们可以在线程上调用`isAlive()`，如果线程未完成则返回`true`。
*   另一种通过使用`join()`方法实现此目的的方法，从父线程调用此方法使父线程等待直到子线程终止。
*   这些方法在`Thread`类中定义。
*   我们在上面的例子中也使用了`isAlive()`方法。

## 同步

*   多线程为程序引入了异步行为。如果一个线程正在写一些数据，那么另一个线程可能正在读取相同的数据。这可能会带来不一致。
*   当两个或多个线程需要访问共享资源时，应该有某种方式资源一次只能由一个资源使用。实现此目的的过程称为同步。
*   要实现同步行为，java 具有同步方法。一旦线程在同步方法中，任何其他线程都不能在同一对象上调用任何其他同步方法。然后所有其他线程一直等到第一个线程从同步块中出来。
*   当我们想要同步访问不是为多线程访问而设计的类的对象时，我们无法获得需要同步访问的方法的代码，在这种情况下，我们无法将`synchronized`添加到适当的方法中。在 java 中我们有这个解决方案，以下列方式调用此类在同步块内定义的方法（需要同步）。

```java
Synchronized(object)
{
    // statement to be synchronized
}
```

## 线程间通信

我们有很少的方法可以让 java 线程相互通信。这些方法是`wait()`，`notify()`，`notifyAll()`。所有这些方法只能在同步方法中调用。

1）了解同步 java 有一个监视器的概念。监视器可以被认为是一个只能容纳一个线程的盒子。一旦线程进入监视器，所有其他线程必须等待该线程退出监视器。

2）`wait()`告诉调用线程放弃监视器并进入休眠状态，直到某个其他线程进入同一个监视器并调用`notify()`。

3）`notify()`唤醒在同一个对象上调用`wait()`的第一个线程。
`notifyAll()`唤醒在同一个对象上调用`wait()`的所有线程。优先级最高的线程将首先运行。

**参考文献**

*   Herbert Schildt 撰写的 Java 2 完整参考