乐趣区

关于后端:Java并发编程理解线程

概念梳理

并发与并行

  • 并发

在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行结束之间,且这几个程序都是在同一个处理机上运行。

  • 并行

当零碎有一个以上 CPU 时,当一个 CPU 执行一个过程时,另一个 CPU 能够执行另一个过程,两个过程互不抢占 CPU 资源,能够同时进行,这种形式咱们称之为并行 (Parallel)。

过程 线程 纤程

  • 过程

    过程是计算机中已运行程序的实体。

  • 线程

    线程是操作系统可能进行运算调度的最小单位。它被蕴含在过程之中,是过程中的理论运作单位。一条线程指的是过程中一个繁多程序的控制流,一个过程中能够并发多个线程,每条线程并行执行不同的工作。

以上内容取自维基百科,从下面的形容来看,过程本质上就是一个程序运行起来的状态;线程就是一个过程中不同的执行门路。从更业余的角度上来看, 过程本质上操作系统分配资源的根本单位;而协程是执行调度的根本单位。(分配资源就好比当你关上一个程序,操作系统在内存上为你划分一块区域来加载你的程序)。每个过程之间的内存空间是独立的,而各个过程内的线程是共享内存空间的,没有本人的独立内存空间。这是过程和线程比拟重大的区别。

  • 纤程

那什么是纤程呢?纤程其实咱们能够了解为线程的线程。零碎执行调度的时候是应用线程作为根本单位,是不可控的,然而咱们又须要肯定的程序执行,这时候就须要应用锁来解决。那纤程的调度,齐全是由用户能够管制的。 纤程还能够了解为用户态的线程 ,他不会波及到用户态与内核态的切换。因为不须要通过操作系统的切换和调度,那么他速度必定也是最快的。纤程相比线程来说,占用的资源也更少。一个线程所占资源大略在 4k 左右,而一个线程则是 1M。

目前反对内置纤程的语言:Go Scala Kotlin Python(须要三方库)

线程的状态

线程共分为 6 个状态,别离是以下:

  • NEW(创立)
  • RUNNABLE(可运行)

    • READY(就绪)
    • RUNNING(正在运行)
  • BLOCK(阻塞)
  • WAITING(无限期期待)
  • TIME WAITING(有限期期待)
  • TERMINATE(终止)

下图形容了线程状态的切换

阻塞与期待的区别就在于阻塞是被动的,该线程正在期待被其余线程先占用的 monitor lock,所以处于阻塞;而期待则是被动去调用办法进入期待状态。

线程的应用

创立线程

创立线程,那么如何创立一个线程呢?Java 中创立线程有 3 种形式。

继承 Thread 类

public class MyThread extends Thread{public void run() {// ...}
}

实现 Runnable 接口

public class MyRunnable implements Runnable {
    @Override
    public void run() {// ...}
}

线程池

public static void main(String[] args) {Executors.newCachedThreadPool(); // 创立一个线程池,该线程池依据须要创立新线程,然而将在先前结构的线程可用时重用它们。Executors.newFixedThreadPool(10);// 创立一个线程池,该线程池重用在共享的无边界队列上运行的固定数量的线程。Executors.newSingleThreadExecutor();// 创立单个线程的线程池,相当于 newFixedThreadPool(1);
    Executors.newScheduledThreadPool(2);// 创立一个线程池,该线程池能够安顿命令在给定的提早后运行或定期执行。Executors.newSingleThreadScheduledExecutor();// 创立一个单线程执行器,该执行器能够打算命令在给定的提早后运行或定期执行。}

线程办法

sleep

sleep 示意睡眠,那么 sleep 的意思就是以后线程暂停一段时间让给别的线程去执行,具体多少工夫取决于你参数设置。

@Override
public void run() {
    try {Thread.sleep(200);
    } catch (InterruptedException e) {e.printStackTrace();
    }
}

yield

yield 有个释义示意放弃,那么 yield 示意的意思就是以后线程正在执行的时候放弃继续执行,回到期待队列中,期待零碎下一次的调度。

@Override
public void run() {Thread.yield();
}

join

join 示意退出,那么 join 示意的意思就是以后线程调用另外一个线程的 join 办法时,会将以后线程挂起,让另外一个线程执行结束之后,以后线程继续执行。

Thread t1 = new Thread(() -> {for (int i = 0; i < 5; i++) {System.out.println("t1:" + i);
        try {TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {e.printStackTrace();
        }
    }

});

Thread t2 = new Thread(() -> {
    try {t1.join();
    } catch (InterruptedException e) {e.printStackTrace();
    }

    for(int i = 0; i < 5; i++) {System.out.println("t2:" + i);
        try {TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {e.printStackTrace();
        }
    }
});
t1.start();
t2.start();

参考链接

过程 线程 协程
CS-Notes/Java 并发
Java 工程师成神之路

退出移动版