920 字
5 分钟
多线程并发编程笔记(基本概念、线程使用、常见方法、两段终止)
2025-10-26

多线程并发编程笔记#

简本概念#

Amdahl定律 S = 1 / (a + (1 - a) / n)

采用并发可以提升的效率

并发和并行

并发(Concurrent):值单核CPU多个程序同时运行,轮流抢占CPU时间片(幻觉自己独占CPU)

并行(Parallel):多核CPU,在不同核心上一起执行(真正的一起执行)

线程与进程

进程是内存分配,资源调度的基本单位,是线程的容器

线程是执行任务的单位,独立子任务,享受进程分配的空间

线程使用#

从方法调用角度来看,需要等待结果返回才可以继续执行那就是同步

不需要等待结果返回就可以运行是异步

为了后续方便调试我们使用日志框架

<configuration>
    <!-- 控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 文件输出 -->
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>logs/app.log</file>
        <encoder>
            <pattern>%d %level [%thread] %logger{10} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 日志级别设置 -->
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    </root>

    <!-- 自定义包级别 -->
    <logger name="com.example" level="DEBUG" />
</configuration>

导入接口

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.34</version>
    <scope>provided</scope>
</dependency>
<!-- SLF4J API(必须) -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.9</version> <!-- 使用最新稳定版 -->
</dependency>

<!-- Logback 实现(经典组合) -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.4.11</version>
</dependency>

使用Lambda来简化创建运行线程

@Slf4j
public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> log.info("创建线程方法执行..."));
        thread.setName("子线程1");
        thread.start();
        log.info("主线程执行...");
    }
}
2025-10-26 14:31:49 [子线程1] INFO  com.Main - 创建线程方法执行...
2025-10-26 14:31:49 [main] INFO  com.Main - 主线程执行...

用Future配合Thread,可以返回结果

@Slf4j
public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> task = new FutureTask<>(() -> {
           log.info("线程01执行...");
           return 100;
        });
        Thread thread = new Thread(task, "thread01");
        thread.start();
        log.info("等待结果返回...");
        Integer integer = task.get();
        log.info("主线程获取参数:" + integer);
    }
}
2025-10-26 14:40:28 [thread01] INFO  com.Main - 线程01执行...
2025-10-26 14:40:28 [main] INFO  com.Main - 等待结果返回...
2025-10-26 14:40:28 [main] INFO  com.Main - 主线程获取参数:100

常见方法#

start:让线程进入就绪状态

run:线程启动后调用的方法

join:等待线程运行结束

join(long n):等待线程运行结束,最多等待n毫秒

getId:获取线程长整型id

getName:获取线程名称

setName(String name):设置线程名

getPriority:获取线程优先级

setPriority(int i):设置线程优先级

getState():获取线程状态

isInterrupted:判断是否被打断-不会清除打断标记

isAlive:线程是否存活

interrupt:打断线程

interrupted:判断当前线程是否被打断-会清除打断标记

currentThread:获取当前正在执行的线程

sleep(long n):让当前执行的线程休眠n毫秒

yield:提示线程调度器让出当前线程

setDaemon(boolean flag):设置守护线程

LockSupport工具类中的part方法:可以暂停线程,如果需要继续执行通过打断完成,我们后续如果还需要part暂停还需要将打断标记重新设计为假

两阶段终止#

在一个线程T1种优雅终止T2,给T2一个料理后事的机会

321

在打断的时候会设置打断标记,注意如果在Sleep中被打断需要再次catch种打断自身,设置打断标记

@Slf4j
public class TwoPhaseTermination {
    private Thread monitor;

    public void start() {
        monitor = new Thread(() -> {
            while (true) {
                log.info("线程方法处理中...");
                Thread current = Thread.currentThread();
                if(current.isInterrupted()) {
                    log.info("后续处理");
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    log.info("在睡眠中打断");
                    current.interrupt();
                }
            }
        });
        monitor.start();
    }

    public void stop() {
        monitor.interrupt();
    }
}

主程序调用

@Slf4j
public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TwoPhaseTermination twoPhase = new TwoPhaseTermination();
        twoPhase.start();
        Thread.sleep(4000);
        twoPhase.stop();
    }
}
多线程并发编程笔记(基本概念、线程使用、常见方法、两段终止)
https://thrinisty.github.io/Blog/posts/多线程并发编程笔记基本概念线程使用常见方法两段终止/
作者
Thrinisty
发布于
2025-10-26
许可协议
CC BY-NC-SA 4.0