基本概念

程序(Program)

程序是为完成特定任务,使用某种语言编写的一组计算机能识别和执行的指令集合。即一段静态的代码

进程(Process)

进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。

进程具有的特征:

动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的;

并发性:任何进程都可以同其他进行一起并发执行;

独立性:进程是系统进行资源分配和调度的一个独立单位;

结构性:进程由程序数据进程控制块(PCB)三部分组成

线程(Thread)

线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程。

进程与线程的区别

  1. 线程是CPU调度的最小单位,而进程操作系统分配资源的最小单位

  2. 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线

  3. 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信号等),某进程内的线程在其他进程不可见;

  4. 调度和切换:线程上下文切换比进程上下文切换要快得多

并行(Parallelism)

多个CPU同时执行多个任务。例如:多个人同时做不同的事

并发(Concurrency)

一个CPU(利用时间片交替执行多个任务,因为一个时间片时间非常短,所以看起来像是”同时执行”。

并行与并发的区别

Java中线程的状态

新创建状态 new

新创建了一个线程对象,但还没有调用start()方法

运行状态 runnable

Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。

阻塞状态 blocked

阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态。

等待状态 waiting

处于这种状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒(调用notify方法或notifyAll方法),否则会处于无限期等待的状态

超时等待状态 timed_waiting

处于这种状态的线程不会被分配CPU执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒

终止状态 terminated

表示该线程已经执行完毕。

当线程的run()方法完成时,或者主线程的main()方法完成时,我们就认为它终止了。

线程状态转换图

线程状态转换图

创建线程的几种方式

实现Runnable接口

1
2
3
4
5
6
7
8
9
10
11
12
13
public class RunnableTest implements Runnable {
@Override
public void run() {
// ... 业务代码
}

public static void main(String[] args) {
// 创建Runnable实现类的实例
RunnableTest test = new RunnableTest();
// 赋值给Thread(Runnable target)构造并开启多线程
new Thread(test).start();
}
}

继承Thread

1
2
3
4
5
6
7
8
9
10
11
public class ThreadTest extends Thread{
@Override
public void run() {
//...业务代码
}
public static void main(String[] args) {
// 开启多线程
new ThreadTest().start();

}
}

实现Callable接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
//...业务代码
return "test";
}
}

public class TestCallable {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// FutureTask类实现了RunnableFuture接口,RunnableFuture接口实现了Runnable接口
// 创建FutureTask实例后赋值给Thread(Runnable target)构造
FutureTask<String> task = new FutureTask<>(new MyCallable());
// ...业务代码
new Thread(task).start();
}
}

线程池创建线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ThreadPoolDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建线程池
ExecutorService threadPool = Executors.newCachedThreadPool();
// submit(Runnable target) submit(Callable task)
Future<String> future = threadPool.submit(new MyCallable());
// 判断子线程是否执行完毕
if (!future.isDone()){
System.out.println("task not finished");
}
// 获取线程执行完成后的返回值
System.out.println("task finished,the return value is :"+ future.get());
// 关闭线程池
threadPool.shutdown();
}
}

sleep()和wait()的区别

  • sleep()是Thread类的方法,wait()是Object类的方法
  • sleep()会让出CPU资源不会导致锁行为的变化
  • wait()不仅会让出CPU资源,还会释放已经占有的同步资源锁