基础概念
- 进程:进程是程序运行资源分配的最小单位
- 线程:线程是CPU调度的最小单位,必须依赖于进程而存在
- 多核心:也指单芯片多处理器(Chip Multiprocessors),CMP 是由美国斯坦福大学提出的,其思想是大规模并行处理器中的SMP(对称多哦处理器)继承到统一芯片照片那个,各个处理器并行执行不同的进程。这种依靠多个CPU同时并行地运行程序是实现超高速计算得一个重要方向,成为并行处理。
- 多线程:Simultaneous Multithreading,简称SMT,让同一个处理器上的多个线程同步执行并共享处理器的执行资源
- 核心数、线程数:目前主流CPU都是多核的。增加核心数目就是为了增加线程数,一般情况下1:1,引入超线程技术后,核心数和线程数形成1:2的关系
- CPU时间片轮转机制:每个进程被分配一个时间段,称作它的时间片,即允许该线程运行的时间。
- 时间片轮转机制原理:如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。调度程序所要做的就是维护一张就绪进程列表,当进程完成它的时间片后,它被移到队列的末尾。
- 并发:应用能够交替执行不同的任务
- 并行:应用能够同时执行不同的任务
- 高并发编程的意义:
- 充分利用CPU的资源
- 加快响应用户时间
- 使代码模块化,异步化,简单化
- 多线程程序注意事项
- 线程之间的安全性
- 线程之间死锁
- 线程太多,导致服务器资源耗尽形成死机宕机
线程的启动与终止
启动
public class ThreadDemo extends Thread{
@Override
public void run() {
System.out.println("extends Thread is started");
}
public static void main(String[] args) {
new ThreadDemo().start();
new Thread(new RunnableDemo()).start();
}
}
class RunnableDemo implements Runnable{
@Override
public void run() {
System.out.println("implements Runnable is started");
}
}
Thread和Runnable的区别:
Thread才是Java里对线程的唯一抽象,Runnable只是对任务的抽象。Thread可以接受任何一个Runnable的实例并执行
其他方法
- yield():使当前线程让出CPU占有权,但让出的时间不可设定,也不会释放锁资源。注意:并不是每个线程都需要这个锁的,而且执行yield()线程不一定就会持有锁,我们完全可以释放锁后再调用yield方法。
- join():把指定线程加入到当前线程,让两个交替执行的线程合并成顺序执行。比如线程B中调用了线程A的join()方法,直到A执行完毕后才会继续执行线程B。
- setPriority(int):设置线程优先级,默认为5,范围是1-10,优先级高的线程分配时间片的数量要多于优先级低的线程。设置线程优先级时,针对频繁阻塞的线程(休眠或I/O操作)的线程需要设置较高的优先级,而偏重计算(需要较多CPU时间或者偏运算)的线程设置较低的优先级,确保处理器不会被独占。在不同的JVM及操作系统上,线程规划会存在差异,有些操作系统甚至会忽略线程优先级。
线程调度
线程调度是指系统为线程分配CPU使用权的过程
协同式线程调度
抢占式线程调度
使用协同式线程调度的多线程系统,线程执行的时间由线程本身来控制,线程把自己的工作执行完之后,要主动通知系统切换到另外一个线程上。使用协同式线程调度的最大好处是实现简单,由于线程要把自己的事情做完后才会通知系统进行线程切换,所以没有线程同步的问题,但是坏处也很明显,如果一个线程出了问题,则程序就会一直阻塞。
使用抢占式线程调度的多线程系统,每个线程执行的时间以及是否切换都由系统决定。在这种情况下,线程的执行时间不可控,所以不会有「一个线程导致整个进程阻塞」的问题出现。
Java中的线程优先级是通过映射到操作系统的原生线程上实现的,所以线程的调度最终取决于操作系统,操作系统中线程的优先级有时并不能和Java中的一一对应,所以Java优先级并不是特别靠谱
Java中的线程是通过映射到操作系统的原生线程上实现的,所以线程的调度最终取决于操作系统,而操作系统级别,OS是以抢占式调度线程,我们可以认为线程是抢占式的。Java虚拟机采用抢占式调度模型,是指优先让可运行池中优先级高的线程占用CPU,如果可运行池中的线程优先级相同,那么就随机选择一个线程,使其占用CPU。处于运行状态的线程会一直运行,直至它不得不放弃CPU。而且操作系统中线程的优先级有时并不能和Java中的一一对应,所以Java优先级并不是特别靠谱。但是在Java中,因为Java没有提供安全的抢占式方法来停止线程,要安全的停止线程只能以协作式的方式。
创建新的线程有几种方式?
两种。There are two ways to create a new thread of execution。来源Thread类注释。