JUC
JUC的全称是:java.util.concurrent
,是 Java 的并发编程的包,后续均为对其的学习。
1.基础概念
1.1.进程和线程
进程是程序的一次执行过程实例。当一个程序被执行,就是从磁盘中加载此程序的代码至内存。
线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给CPU执行。
Java 中,线程作为最小调度单位,进程作为资源分配的的最小单位。 一个进程在其执行的过程中可以产生多个线程,同一个进程的多个线程共享堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈。
1.2.并发和并行
并发是程序上的逻辑,而并行是物理上的概念。
如果程序是采用多线程的技术编写的,那么运行在单核单线程的机器上,就会并发执行;运行在多核多线程的机器上,就会并行执行。
程序员最关心的是并发,程序可不可以并行,取决于操作系统和硬件。
2.Thread
在进行并发编程编码时,最关心的就是异步线程如何去执行任务。在Java 中,当我们启动 main 函数时其实就是启动了一个 JVM 的进程,而 main 函数所在的线程就是这个进程中的一个线程,也称主线程。
2.1.线程状态
在 Java 中,java.lang.Thread.State
中表明,线程在运行的生命周期中的指定时刻只可能处于下面 6 种不同状态的其中一个状态:
- NEW:初始状态,线程被创建出来但没有被调用 start()
- RUNNABLE: 运行状态,线程被调用了 start()等待运行的状态
- BLOCKED:阻塞状态,需要等待锁释放
- WAITING:等待状态,表示该线程需要等待其他线程做出一些特定动作(通知或中断)
- TIME_WAITING:超时等待状态,可以在指定的时间后自行返回而不是像 WAITING 那样一直等待
- TERMINATED:终止状态,表示该线程已经运行完毕。
2.2.创建启动线程
创建一个线程,启动线程执行方法,共有 3
种:
- 直接使用
Thread
java/** * 使用 Thread 创建和启动线程 */ @Test public void test01() { Thread thread = new Thread("Thread") { @Override public void run() { log.info("使用 Thread 线程名为:{}", Thread.currentThread().getName()); } }; thread.start(); log.info("test01 主线程:{},结束执行......", Thread.currentThread().getName()); }
- 使用
Runnable
接口配合Thread
java/** * Runnable 为可运行的任务,Thread 代表线程 */ @Test public void test02() { Runnable runnable = () -> { log.info("使用 Runnable 搭配 Thread 线程名为:{}", Thread.currentThread().getName()); }; Thread thread = new Thread(runnable, "Runnable"); thread.start(); log.info("test02 主线程:{},结束执行......", Thread.currentThread().getName()); }
- 使用
FutureTask
配合Thread
java/** * FutureTask 可以返回结果,Thread 代表线程 */ @Test @SneakyThrows public void test03() { FutureTask<Integer> futureTask = new FutureTask<>(() -> { log.info("使用 FutureTask 搭配 Thread 线程名为:{}", Thread.currentThread().getName()); return 100; }); Thread thread = new Thread(futureTask, "futureTask"); thread.start(); log.info("test03 主线程:{},结束执行......", Thread.currentThread().getName()); log.info("获取 futureTask 返回的结果:{}", futureTask.get()); }
2.3.线程方法
Thread
类的方法有:
methodName | 含义 |
---|---|
run() | 线程执行逻辑 |
start() | 启动线程,只能启动一次 |
sleep() | 休眠 |
yield() | 让别的线程先执行 |
join() |
sleep()
java
/**
* sleep()方法演示
* 其它线程可以使用 interrupt 方法打断正在水面的线程,此时会抛出 InterruptedException
* 睡眠结束后的线程未必会立刻得到执行,需要等时间片
* 建议使用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性
*/
@Test
@SneakyThrows
public void test04() {
Thread thread = new Thread(() -> {
log.info("{}:sleeping.......", Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
log.info("{}:wake up...", Thread.currentThread().getName());
e.printStackTrace();
}
}, "cat");
thread.start();
Thread.sleep(1000);
log.info("{}:interrupt...", Thread.currentThread().getName());
thread.interrupt();
}
- 线程优先级
java
/**
* 线程优先级
* 可以设置优先级,但具体实现依赖CPU的时间片
*/
@Test
public void test05() {
Thread t1 = new Thread(() -> {
log.info("{},的优先级更高");
}, "t1");
t1.setPriority(1);
t1.start();
}