千家信息网

Java中怎么保证线程顺序执行

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,小编给大家分享一下Java中怎么保证线程顺序执行,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!只要了解过多线程,我们就知道
千家信息网最后更新 2026年11月01日Java中怎么保证线程顺序执行

小编给大家分享一下Java中怎么保证线程顺序执行,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

只要了解过多线程,我们就知道线程开始的顺序跟执行的顺序是不一样的。如果只是创建三个线程然后执行,最后的执行顺序是不可预期的。这是因为在创建完线程之后,线程执行的开始时间取决于CPU何时分配时间片,线程可以看成是相对于的主线程的一个异步操作。

public class FIFOThreadExample {    public synchronized static void foo(String name) {        System.out.print(name);    }    public static void main(String[] args) {        Thread thread1 = new Thread(() -> foo("A"));        Thread thread2 = new Thread(() -> foo("B"));        Thread thread3 = new Thread(() -> foo("C"));        thread1.start();        thread2.start();        thread3.start();    }}

输出结果:ACB/ABC/CBA...

那么我们该如何保证线程的顺序执行呢?

如何保证线程的顺序执行?

1. 使用Thread.join()实现

Thread.join()的作用是让父线程等待子线程结束之后才能继续运行。以上述例子为例,main()方法所在的线程是父线程,在其中我们创建了3个子线程A,B,C,子线程的执行相对父线程是异步的,不能保证顺序性。而对子线程使用Thread.join()方法之后就可以让父线程等待子线程运行结束后,再开始执行父线程,这样子线程执行被强行变成了同步的,我们用Thread.join()方法就能保证线程执行的顺序性。

public class FIFOThreadExample {        public static void foo(String name) {        System.out.print(name);    }    public static void main(String[] args) throws InterruptedException{        Thread thread1 = new Thread(() -> foo("A"));        Thread thread2 = new Thread(() -> foo("B"));        Thread thread3 = new Thread(() -> foo("C"));        thread1.start();        thread1.join();        thread2.start();        thread2.join();        thread3.start();    }}

输出结果:ABC

2. 使用单线程线程池来实现

另一种保证线程顺序执行的方法是使用一个单线程的线程池,这种线程池中只有一个线程,相应的,内部的线程会按加入的顺序来执行。

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class FIFOThreadExample {    public static void foo(String name) {        System.out.print(name);    }    public static void main(String[] args) throws InterruptedException{        Thread thread1 = new Thread(() -> foo("A"));        Thread thread2 = new Thread(() -> foo("B"));        Thread thread3 = new Thread(() -> foo("C"));        ExecutorService executor = Executors.newSingleThreadExecutor();        executor.submit(thread1);        executor.submit(thread2);        executor.submit(thread3);        executor.shutdown();    }}

输出结果:ABC

3. 使用volatile关键字修饰的信号量实现

上面两种的思路都是让保证线程的执行顺序,让线程按一定的顺序执行。这里介绍第三种思路,那就是线程可以无序运行,但是执行结果按顺序执行。
你应该可以想到,三个线程都被创建并start(),这时候三个线程随时都可能执行run()方法。因此为了保证run()执行的顺序性,我们肯定需要一个信号量来让线程知道在任意时刻能不能执行逻辑代码。
另外,因为三个线程是独立的,这个信号量的变化肯定需要对其他线程透明,因此volatile关键字也是必须要的。

public class TicketExample2 {    //信号量    static volatile int ticket = 1;    //线程休眠时间    public final static int SLEEP_TIME = 1;    public static void foo(int name){        //因为线程的执行顺序是不可预期的,因此需要每个线程自旋        while (true) {            if (ticket == name) {                try {                    Thread.sleep(SLEEP_TIME);                    //每个线程循环打印3次                    for (int i = 0; i < 3; i++) {                        System.out.println(name + " " + i);                    }                } catch (InterruptedException e) {                    e.printStackTrace();                }                //信号量变更                ticket = name%3+1;                return;            }        }    }    public static void main(String[] args) throws InterruptedException {        Thread thread1 = new Thread(() -> foo(1));        Thread thread2 = new Thread(() -> foo(2));        Thread thread3 = new Thread(() -> foo(3));        thread1.start();        thread2.start();        thread3.start();    }}

执行结果:
1 0
1 1
1 2
2 0
2 1
2 2
3 0
3 1
3 2

4. 使用Lock和信号量实现

此种方法的思想跟第三种方法是一样的,都是不考虑线程执行的顺序而是考虑用一些方法控制线程执行业务逻辑的顺序。这里我们同样用一个原子类型信号量ticket,当然你可以不用原子类型,这里我只是为了保证自增操作的线程安全。然后我们用了一个可重入锁ReentrantLock。用来给方法加锁,当一个线程拿到锁并且标识位正确的时候开始执行业务逻辑,执行完毕后唤醒下一个线程。
这里我们不需要使用while进行自旋操作了,因为Lock可以让我们唤醒指定的线程,所以改成if就可以实现顺序的执行。

public class TicketExample3 {    //信号量    AtomicInteger ticket = new AtomicInteger(1);    public Lock lock = new ReentrantLock();    private Condition condition1 = lock.newCondition();    private Condition condition2 = lock.newCondition();    private Condition condition3 = lock.newCondition();    private Condition[] conditions = {condition1, condition2, condition3};    public void foo(int name) {        try {            lock.lock();            //因为线程的执行顺序是不可预期的,因此需要每个线程自旋            System.out.println("线程" + name + " 开始执行");            if(ticket.get() != name) {                try {                    System.out.println("当前标识位为" + ticket.get() + ",线程" + name + " 开始等待");                    //开始等待被唤醒                    conditions[name - 1].await();                    System.out.println("线程" + name + " 被唤醒");                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            System.out.println(name);            ticket.getAndIncrement();            if (ticket.get() > 3) {                ticket.set(1);            }            //执行完毕,唤醒下一次。1唤醒2,2唤醒3            conditions[name % 3].signal();        } finally {            //一定要释放锁            lock.unlock();        }    }    public static void main(String[] args) throws InterruptedException {        TicketExample3 example = new TicketExample3();        Thread t1 = new Thread(() -> {            example.foo(1);        });        Thread t2 = new Thread(() -> {            example.foo(2);        });        Thread t3 = new Thread(() -> {            example.foo(3);        });        t1.start();        t2.start();        t3.start();    }}

输出结果:
线程2 开始执行
当前标识位为1,线程2 开始等待
线程1 开始执行
1
线程3 开始执行
当前标识位为2,线程3 开始等待
线程2 被唤醒
2
线程3 被唤醒
3

上述的执行结果并非唯一,但可以保证打印的顺序一定是123这样的顺序。

以上是"Java中怎么保证线程顺序执行"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

线程 顺序 保证 方法 信号 结果 信号量 三个 标识 输出 时间 篇文章 逻辑 运行 业务 关键 关键字 内容 原子 只是 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 云南咖啡 广州大一互联网络科技有限公司 互联网和科技创新 互联网科技金融 合肥互联网科技公司 上海卓越科技 互联网 互联网科技英文翻译 多迪互联网科技有限公司 深圳前海聚择互联网科技有限公司 广州新华互联网科技学校电竞方面 互联网方面的科技前沿 上海京穆互联网科技有限公司 互联网公司高科技产品 江苏互联网智能科技软件 广州梦谷互联网科技有限公司领导 福州德业互联网科技 艺电能源互联网科技有限公司招聘 长沙渺峰互联网科技有限公司 北京军民互联网科技公司 每日互联网科技新闻 金融科技还是互联网 北京三清互联网科技 世界互联网科技公司市值排名 岳阳华臻互联网科技有限公司 厦门千工互联网科技有限公司 成都互联网科技公司工作好不好 南通创西澳互联网科技有限公司 互联网科技新闻 互联网科技大佬云集 优雇互联网科技有限公司
0