java多线程打印

模块一:线程交替打印(奇数 / 偶数,1~10)

synchronized + wait()/notify() 实现

java 复制代码
/**
 * 线程交替打印 1~10(奇数线程 + 偶数线程)
 * 核心:synchronized 加锁 + wait()/notify() 线程通信,实现交替执行
 */
public class AlternatePrintDemo {
    // 1. 共享计数器(控制打印数字,从1开始)
    private static int count = 1;
    // 2. 共享锁对象(保证线程安全,作为线程通信的载体)
    private static final Object LOCK = new Object();

    public static void main(String[] args) {
        // 线程1:打印奇数(1、3、5、7、9)
        Thread oddThread = new Thread(() -> printOdd(), "奇数线程");
        // 线程2:打印偶数(2、4、6、8、10)
        Thread evenThread = new Thread(() -> printEven(), "偶数线程");

        // 启动线程(启动顺序不影响结果)
        oddThread.start();
        evenThread.start();
    }

    /**
     * 打印奇数逻辑
     */
    private static void printOdd() {
        while (count <= 10) {
            synchronized (LOCK) { // 加锁:获取LOCK对象的监视器锁
                try {
                    // 不是奇数,进入等待(释放锁,等待偶数线程唤醒)
                    if (count % 2 == 0) {
                        LOCK.wait();
                    }
                    // 打印奇数并自增
                    if (count <= 10) {
                        System.out.println(Thread.currentThread().getName() + ":" + count);
                        count++;
                    }
                    // 唤醒等待在LOCK上的另一个线程(偶数线程)
                    LOCK.notify();
                } catch (InterruptedException e) {
                    // 中断异常处理:恢复线程中断状态,符合最佳实践
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    /**
     * 打印偶数逻辑
     */
    private static void printEven() {
        while (count <= 10) {
            synchronized (LOCK) { // 加锁:获取LOCK对象的监视器锁
                try {
                    // 不是偶数,进入等待(释放锁,等待奇数线程唤醒)
                    if (count % 2 == 1) {
                        LOCK.wait();
                    }
                    // 打印偶数并自增
                    if (count <= 10) {
                        System.out.println(Thread.currentThread().getName() + ":" + count);
                        count++;
                    }
                    // 唤醒等待在LOCK上的另一个线程(奇数线程)
                    LOCK.notify();
                } catch (InterruptedException e) {
                    // 中断异常处理:恢复线程中断状态,符合最佳实践
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
}

打印结果:

java 复制代码
奇数线程:1
偶数线程:2
奇数线程:3
偶数线程:4
奇数线程:5
偶数线程:6
奇数线程:7
偶数线程:8
奇数线程:9
偶数线程:10

模块二:线程等待打印(线程 1 先执行,线程 2 后执行)

方案 A:Thread.join () 经典实现(极简代码)

java 复制代码
/**
 * 线程等待打印:线程1先执行完毕,线程2再执行(Thread.join() 经典方案)
 * 核心:join() 让主线程阻塞等待线程1,再启动线程2
 */
public class WaitPrintByJoinDemo {
    public static void main(String[] args) {
        // 线程1:打印 1~3
        Thread thread1 = new Thread(() -> {
            for (int i = 1; i <= 3; i++) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
                sleep(500); // 模拟耗时,让效果更直观
            }
            System.out.println(Thread.currentThread().getName() + " 执行完毕");
        }, "线程1");

        // 线程2:打印 A~C
        Thread thread2 = new Thread(() -> {
            for (char c = 'A'; c <= 'C'; c++) {
                System.out.println(Thread.currentThread().getName() + ":" + c);
                sleep(500); // 模拟耗时
            }
            System.out.println(Thread.currentThread().getName() + " 执行完毕");
        }, "线程2");

        // 步骤1:启动线程1
        thread1.start();

        // 步骤2:主线程等待线程1执行完毕(核心:join())
        try {
            thread1.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        // 步骤3:线程1执行完毕后,再启动线程2
        thread2.start();
    }

    /**
     * 极简睡眠工具方法(避免重复 try-catch)
     */
    private static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

打印结果:

java 复制代码
线程1:1
线程1:2
线程1:3
线程1 执行完毕
线程2:A
线程2:B
线程2:C
线程2 执行完毕

方案 B:CompletableFuture 优雅实现(JDK8+)

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * 线程等待打印:线程1先执行完毕,线程2再执行(CompletableFuture 优雅方案)
 * 核心:thenRunAsync() 实现任务依赖,无需手动管理线程和join()
 */
public class WaitPrintByCompletableFutureDemo {
    public static void main(String[] args) {
        // 任务1(对应线程1):打印 1~3
        CompletableFuture<Void> task1 = CompletableFuture.runAsync(() -> {
            for (int i = 1; i <= 3; i++) {
                System.out.println("线程1:" + i);
                sleep(500);
            }
            System.out.println("线程1 执行完毕");
        });

        // 任务2(对应线程2):依赖任务1执行完毕后执行,打印 A~C
        CompletableFuture<Void> task2 = task1.thenRunAsync(() -> {
            for (char c = 'A'; c <= 'C'; c++) {
                System.out.println("线程2:" + c);
                sleep(500);
            }
            System.out.println("线程2 执行完毕");
        });

        // 主线程等待任务2执行完毕(可选,根据需求决定)
        task2.join();
    }

    /**
     * 极简睡眠工具方法
     */
    private static void sleep(long millis) {
        try {
            TimeUnit.MILLISECONDS.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

打印结果:

java 复制代码
线程1:1
线程1:2
线程1:3
线程1 执行完毕
线程2:A
线程2:B
线程2:C
线程2 执行完毕
相关推荐
腻害兔4 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社5 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
萧瑟余晖6 小时前
JDK 26 新特性详解
java·开发语言
马优晨7 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
维天说9 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
Zane199410 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
噢,我明白了11 小时前
java中Excel的导入和导出(EasyExcel)
java·开发语言·excel
吠品11 小时前
Zabbix Web界面误报Server未运行的排查与解决
java·服务器·数据库
啊湘11 小时前
天气查询API接口 按月Token鉴权 实时天气 物联网可用 文档齐全
java·后端·struts
Java内核笔记11 小时前
告别十亿美元的错误 : Spring Boot 4 空安全 (JSpecify) 实战
java·spring boot·后端