# Thread 多线程基础

![Java 线程声明周期](https://3876120153-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MeAUhQfs4IbJtX3pwu_%2F-MeUR0PwsxMJWNWkBEfp%2F-MeURLMzEIi6-wEQ_sav%2Fthread.png?alt=media\&token=d39054e0-90d7-41d3-aa5c-5bf91d83f890)

Java 多线程的创建有两种形式:

1. 一个类继承 Thread，重写 run 方法，再实例化这个类。
2. 一个类实现Runnable 接口，重写 run 方法，在实例化这个类(更加常用)。

实际应用中第二种方法更常见, 因为Java不支持多继承, 通过实现接口更加方便。

## 方法1实现多**线程**:

我们编写了一个 EasyThread 类 继承了 Thread 类，重写了 run 方法。

特别的是 EasyThread 可以直接调用 Thread 的构造函数。在方法1下，Thread 提供2种构造函数:

|         构造函数        |       含义      |
| :-----------------: | :-----------: |
|       Thread()      |    创建一个线程对象   |
| Thread(String name) | 创建一个指定名称的线程对象 |

线程的任务非常简单, 输出数字0-9。

值得一提的是, thread.getName()  方法返回当前线程的名称。

```java
public  class EasyThread extends Thread{
    public EasyThread(String name){
        super(name);
    }

    public EasyThread(){
    }

    //线程的启动需要重写 run 方法
    @Override
    public void run(){
        for (int i = 0; i < 10; i++) {
            System.out.println(this.getName()+"线程正在执行"+"第"+i+"次for循环");
        }
    }
}
```

我们编写了一个测试类 EasyThreadDemo。这里面我们实现了两个线程 mt1 和 mt2 。线程的启动需要调用线程对象的 start()方法。两个线程任务相同。

```java
public class EasyThreadDemo {
    public static void main(String[] args) {
        EasyThread mt1=new EasyThread("mt1");
        mt1.start();//启动线程, star()方法去启动run()方法

        EasyThread mt2=new EasyThread("mt2");
        mt2.start();

    }
}
```

![输出结果](https://3876120153-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MeAUhQfs4IbJtX3pwu_%2F-MeURc8sAtxWLi3_Fk7R%2F-MeUVDzsRCo1KqUbkx92%2Feasythreaddemo.png?alt=media\&token=c87d4b48-e082-407b-ba49-702bbda6e052)

可以看出多线程的执行顺序和我们在 main 函数里面所写的顺序不同。main 函数里面明明是先启动了 mt1 线程，但是执行的时候却是 mt2 线程 先执行。

而事实上，**线程的实行顺序是随机的，或者说是由操作系统动态决定的！**

上图中的执行顺序也是不确定，可能每一次运行的执行顺序都不同

## 方法2实现多**线程**:

我们编写了一个 RunnableThread 类, 实现了 Runnable 接口， 重写了run 方法。

然后将 实现了 Runnable 接口 的对象传给 Thread 类，构建一个线程对象。在此种方法下，Thread 也提供2种构造函数:&#x20;

|                 构造函数                 |       说明      |
| :----------------------------------: | :-----------: |
|        Thread(Runnable target)       |    创建一个线程对象   |
| Thread(Runnable target, String name) | 创建一个指定名称的线程对象 |

线程的任务非常简单, 也是输出数字0-9。

值得一提的, Thread.currentThread().getName() 也能获取当前线程的名城

```java
public class RunnableThread implements  Runnable{

    @Override
    public void run() {
        for (int i=0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"正在运行"+"第"+i+"次for循环.");
        }

    }
}
```

我们编写了一个测试类，实例化了一个实现Runnable 接口的对象, 将这个对象传给  Thread, 构建了两个线程。

```java
public class RunnableThreadDemo {
    public static void main(String[] args) {
        //创建 实现 Runnable 接口的对象
        RunnableThread rt= new RunnableThread();

        //创建线程,传入实现Runnable接口的对象
        Thread t1=new Thread(rt,"runnable thread 1");

        //启动线程
        t1.start();

        //将同一个 实现 Runnable 接口的对象 传给多个线程
        //相当于多线程共同处理 实现 Runnable 接口的对象 内的数据
        Thread t2=new Thread(rt,"runnable thread 2");
        t2.start();

    }

}
```

![输出结果](https://3876120153-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MeAUhQfs4IbJtX3pwu_%2F-MeUW4hsoR3H9LL55W3D%2F-MeV-OS1TCG_mqey8d-Y%2FRunnableThreadDemo.png?alt=media\&token=eba1cf15-5cee-4828-b407-3be2eed59e2f)

这个例子进一步看出, 线程的执行顺序是随机的, 是交替执行的。具体来说，**线程的执行顺序是由操作系统动态决定的。**
