精华内容
下载资源
问答
  • 如何保证线程顺序执行的四种方法
    2021-06-03 17:28:35

    join

    thread.join();使主线程等待thread执行完毕。

    单线程池

    使用Executors.newSingleThreadExecutor(),创建单线城池,然后顺序提交任务以保证线程的顺序执行。

    volatile

    使用volatile关键字,使共享变量可见。通过判断变量的值,配合thread.wait()/notify()/notifyAll(),达到控制线程顺序的目的。

    Condition

    使用ReentrantLock的 Condition condition = lock.newCondition();condition.await()/singal();

    更多相关内容
  • 使用单线程线程池来实现 另一种保证线程顺序执行的方法是使用一个单线程的线程池,这种线程池中只有一个线程,相应的,内部的线程会按加入的顺序来执行。 import java.util.concurrent.ExecutorService; import ...

    我是猿人,一个热爱技术、热爱编程的IT猿。技术是开源的,知识是共享的!

    写作是对自己学习的总结和记录,如果您对 Java、分布式、微服务、中间件、Spring Boot、Spring Cloud等技术感兴趣,可以关注我的动态,我们一起学习,一起成长!

    用知识改变命运,让家人过上更好的生活,互联网人一家亲!

    ---公众号猿码天地

    Java知识学堂https://gitee.com/zhangbw666/it-knowledge

    你多学一样本事,就少说一句求人的话,现在的努力,是为了以后的不求别人,实力是最强的底气。记住,活着不是靠泪水博得同情,而是靠汗水赢得掌声。——《写给程序员朋友》 

      作者 |  六层楼

    来源 |  urlify.cn/IVz6vm

    只要了解过多线程,我们就知道线程开始的顺序跟执行的顺序是不一样的。如果只是创建三个线程然后执行,最后的执行顺序是不可预期的。这是因为在创建完线程之后,线程执行的开始时间取决于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...

    那么我们该如何保证线程的顺序执行呢?(搜索公众号【猿码天地】,回复“BAT面试”,送你一份Java面试题宝典)

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

    1. 使用Thread.join()实现

    Thread.join()的作用是让父线程等待子线程结束之后才能继续运行。以上述例子为例,main()方法所在的线程是父线程,在其中我们创建了3个子线程A,B,C,子线程的执行相对父线程是异步的,不能保证顺序性。而对子线程使用Thread.join()方法之后就可以让父线程等待子线程运行结束后,再开始执行父线程,这样子线程执行被强行变成了同步的,我们用Thread.join()方法就能保证线程执行的顺序性。(搜索公众号【猿码天地】,回复“BAT面试”,送你一份Java面试题宝典)

    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关键字也是必须要的。(搜索公众号【猿码天地】,回复“BAT面试”,送你一份Java面试题宝典)

    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。用来给方法加锁,当一个线程拿到锁并且标识位正确的时候开始执行业务逻辑,执行完毕后唤醒下一个线程。(搜索公众号【猿码天地】,回复“BAT面试”,送你一份Java面试题宝典)
    这里我们不需要使用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这样的顺序。

    点赞&在看是最大的支持
    
    展开全文
  • 只要了解过多线程,我们就知道线程开始的顺序执行顺序是不一样的。如果只是创建三个线程然后执行,最后的执行顺序是不可预期的。这是因为在创建完线程之后,线程执行的开始时间取决于CPU何时分配时间片,线程...

    只要了解过多线程,我们就知道线程开始的顺序跟执行的顺序是不一样的。如果只是创建三个线程然后执行,最后的执行顺序是不可预期的。这是因为在创建完线程之后,线程执行的开始时间取决于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 多线程 实现多个线程的顺序执行 - Hoonick - 博客园 (cnblogs.com)
    Java lock锁的一些细节_笔记小屋-CSDN博客
    VolatileCallSite (Java Platform SE 8 ) (oracle.com)
    java保证多线程的执行顺序 - james.yj - 博客园 (cnblogs.com)

    展开全文
  • 主要介绍了java多线程如何按指定顺序同步执行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 在面试的时候是一定会被询问的话题,今天,在和朋友聊天的时候,他问了我一道很好玩的多线程面试题,不难,但是想解释清楚,还真的是不容易问题:现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,...

    作为面试宠儿的多线程,在面试的时候是一定会被询问的话题,今天,在和朋友聊天的时候,他问了我一道很好玩的多线程面试题,不难,但是想解释清楚,还真的是不容易

    问题:现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行

    当看到这个问题的时候,我的第一反应就是wait、notify(会在后面附上代码+解释),然后脑子里闪过好多不同的方案,那我们就来看一下我的第一反应是如何处理的

    分析:

    Thread类中的join方法是用来同步的,底层其实是调用了 wait方法。先来看一下演示代码:

    package com.whh.concurrency;

    /**

    *@description:

    * 问题:现在有 T1、T2、T3 三个线程,怎样保证 T2 在 T1 执行完后执行T3在T2执行完

    * 分析:使用join方法实现

    *@author:wenhuohuo

    */

    public class MyJoin {

    public static void main(String[] args) {

    final Thread t1 = new Thread(new Runnable() {

    @Override

    public void run() {

    System.out.println("线程1");

    }

    },"t1");

    final Thread t2 = new Thread(new Runnable() {

    @Override

    public void run() {

    try {

    t1.join();

    } catch (Exception e) {

    e.printStackTrace();

    }

    System.out.println("线程2");

    }

    },"t2");

    final Thread t3 = new Thread(new Runnable() {

    @Override

    public void run() {

    try {

    t2.join();

    }catch (Exception e){

    e.printStackTrace();

    }

    System.out.println("线程3");

    }

    },"t3");

    t3.start();

    t2.start();

    t1.start();

    }

    }

    执行结果:

    线程1

    线程2

    线程3

    可以看到,我们让t2线程调用t1.join,t3调用t2.join,尽管是t3,t2,t1分别start,执行顺序还是t1,t2,t3。是因为join方法底层使用的是wait方法。

    查看join方法源码

    public final void join() throws InterruptedException {

    join(0); //传入的是毫秒值

    }

    public final synchronized void join(long millis)

    throws InterruptedException {

    long base = System.currentTimeMillis();

    long now = 0;

    if (millis < 0) {

    throw new IllegalArgumentException("timeout value is negative");

    }

    if (millis == 0) {

    while (isAlive()) { //isAlive()是native方法,判断线程是否还存活

    wait(0);//wait(0),不计时间,一直等待,直到有notify()或notifyAll()来唤醒。

    }

    } else {

    while (isAlive()) {

    long delay = millis - now;

    if (delay <= 0) {

    break;

    }

    wait(delay);//传入时间,表示在时间值消耗完之前一直等待,直到过了等待时间。

    now = System.currentTimeMillis() - base;

    }

    }

    }

    1)从源码中,我们结合之前的代码分析,t2.join()和t3.join(),均没有传值,相当于join(0),表示不计时间,t2会一直wait等待t1执行完成,t3会一直wait等待t2执行完成。所以执行结果顺序是t3,t2,t1。

    2)当传入的毫秒值不为0时,就一直循环等待,直到过了等待时间(dalay<=0),则执行break方法,那么将不再等待。

    改变join()传入的毫秒值,查看执行顺序并分析结果:

    public class MyJoin {

    public static void main(String[] args) {

    final Thread t1 = new Thread(new Runnable() {

    @Override

    public void run() {

    try {

    //处理业务时间,模拟为8秒

    Thread.sleep(8000);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    System.out.println("线程1");

    }

    },"t1");

    final Thread t2 = new Thread(new Runnable() {

    @Override

    public void run() {

    try {

    t1.join(4000); //t2等待t1线程4秒

    } catch (Exception e) {

    e.printStackTrace();

    }

    System.out.println("线程2");

    }

    },"t2");

    final Thread t3 = new Thread(new Runnable() {

    @Override

    public void run() {

    try {

    t2.join(2000); //t3等待t2线程2秒

    }catch (Exception e){

    e.printStackTrace();

    }

    System.out.println("线程3");

    }

    },"t3");

    t3.start();

    t2.start();

    t1.start();

    }

    }

    执行结果:

    线程3//程序启动过了2秒执行t3

    线程2 //过了4秒执行t2

    线程1 //过了8秒执行t1

    分析:我们让t1 睡眠8秒模拟业务执行时间,t2等待t1 的时间为4秒,t3等待t2的时间为2秒。那么当t1,t2,t3启动后,等待的时间,t3会因为t2的等待时间4秒太长而先与t2执行,t2会因为t1的8秒太长而先与t1执行。

    好了,到这里不知道大家感觉怎么样,有没有想明白,其实,关于多线程顺序执行的问题,我总结了一个万能的解答方法,通过一个小例子进行演示

    例题描述:建立三个线程,A线程打印100次A,B线程打印100次B,C线程打印100次C,要求线程同时运行,交替打印100次ABC。这个问题用Object的wait(),notify()就可以很方便的解决。

    代码如下:

    public class QueueThread implements Runnable{

    private Object current;

    private Object next;

    private int max=100;

    private String word;

    public QueueThread(Object current, Object next, String word) {

    this.current = current;

    this.next = next;

    this.word = word;

    }

    @Override

    public void run() {

    // TODO Auto-generated method stub

    for(int i=0;i

    synchronized (current) {

    synchronized (next) {

    System.out.println(word);

    next.notify();

    }

    try {

    current.wait();

    } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    //必须做一下这样处理,否则thread1-thread4停不了

    synchronized (next) {

    next.notify();

    System.out.println(Thread.currentThread().getName()+"执行完毕");

    }

    }

    public static void main(String[] args) throws InterruptedException {

    long startTime = System.currentTimeMillis();

    Object a = new Object();

    Object b = new Object();

    Object c = new Object();

    Object d = new Object();

    Object e = new Object();

    //之所以每次当前线程都要sleep(10)是为了保证线程的执行顺序

    new Thread(new QueueThread(a,b,"a")).start();

    Thread.sleep(10);

    new Thread(new QueueThread(b,c,"b")).start();

    Thread.sleep(10);

    new Thread(new QueueThread(c,d,"c")).start();

    Thread.sleep(10);

    new Thread(new QueueThread(d,e,"d")).start();

    Thread.sleep(10);

    Thread thread4 = new Thread(new QueueThread(e,a,"e"));

    thread4.start();

    thread4.join();//因为线程0-4停止是依次执行的,所以如果保证主线程在线程4后停止,那么就能保证主线程是最后关闭的

    System.out.println("程序耗时:"+ (System.currentTimeMillis()-startTime ));

    }

    }

    其实这个程序很容易理解,首先,我们保证了线程0-线程4依次启动,并设置了Thread.sleep(10),保证线程0-4依次执行他们的run方法。

    其次,我们看QueueThread的run()便可知:1.线程获得current锁,2.获得next锁。3.打印并notify拥有next锁的一个对象4.线程执行current.wait(),释放current锁对象,并使线程处于阻塞状态。

    然后,假设已经执行到了thread-4的run方法,那么此时的情况是这样的:

    线程0处于阻塞状态,需要a.notify()才能使其回到runnale状态

    线程1处于阻塞状态,需要b.notify()才能使其回到runnale状态

    线程2处于阻塞状态,需要c.notify()才能使其回到runnale状态

    线程3处于阻塞状态,需要d.notify()才能使其回到runnale状态

    而线程4恰好可以需要执行a.notify(),所以能够使线程0回到runnale状态。然后执行e,wait()方法,使自身线程阻塞,需要e.notify()才能唤醒。

    依次执行下去,就可以发现规律了!

    最后之所以要在for循环后加上一个处理,是因为,如果不进行处理,除了线程0能够结束for循环,其余线程1-4实际上是会停在current,wait()这句代码的。

    假设已经执行到最后一次循环了,此时线程4唤醒线程0,并将自身阻塞。线程0被唤醒后,继续执行,然而因为i=max的缘故,它无法再进入循环了。然而如果循环后没有唤醒下一个线程的操作的话,那么剩下的线程1-4就会一直处于阻塞状态!也就不会停止了。但是加了处理之后就完美解决了。

    好啦,到这里两个小实例就讲完了,不知道通过这两个小实例有没有让你很好的理解这道面试题呢?有问题的话,下方评论区,大家一起讨论吧

    欢迎大家关注我,一个脑回路清奇的程序猿,在娱乐中学习是我的真谛,大家一起努力进步

    f35b4c9d1283e84e5642f72200e89646.png

    展开全文
  • 主要介绍了浅谈Python3多线程之间的执行顺序问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 为了确保三个线程顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成; 这里主要是利用Join的阻塞效果,来达到我们的使用目的。进入join源码后,首先看到的是一个传入0参数的join方法...
  • 如何确保三个线程顺序执行

    千次阅读 2021-02-25 19:16:04
    一、使用jointhread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。t.join(); //调用join方法...
  • java中如何保证线程顺序执行

    千次阅读 2019-07-30 17:59:47
    如何保证线程顺序执行 代码: public class ThreadDemo { static Thread threadA = new Thread(()->{ System.out.println("线程A"); }); ​ static Thread threadB = new Thread(()->{ System.out....
  • Java—如何保证线程顺序执行

    千次阅读 2020-01-08 18:41:09
    当多个线程执行任务时,可以通过Thread.join()方法保证线程执行顺序,其内部是通过调用主线程的wait方法,使主线程等待;当子线程执行完成后,再唤醒主线程。 下面写一个简单的实例:创建ABCD四个线程,每个线程...
  • 一、Thread的join方法 public static void ... System.out.println(“线程1执行”)); Thread t2 = new Thread(() -> { try { t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } System
  • 有T1,T2,T3,怎样保证他们按照T1,T2,T3顺序执行 public static void main(String[] args) throws InterruptedException { System.out.println("main start"); Thread t1 = new Thread(new Worker("thread-1"))...
  • 线程并发保证线程顺序执行

    千次阅读 2020-01-04 17:14:25
    线程并发保证线程顺序执行 考虑为什么在并发的情况下要保证线程的并发执行 考虑到可能有如下几种情况 1.单纯面试 现场顺序执行的考点就是线程间的通信问题 2.真正的业务需求,如解析XML 我们想并发执行xml下多个...
  • 如何保证线程顺序执行

    千次阅读 2019-03-20 21:39:46
    线程情况下由于会有CPU在不同线程之间的来回切换,各个线程执行结果会产生交叉 。 举个例子:现有T1、T2、T3、主线程四个线程,如何安照T1执行完才执行T2、T2执行完才执行T3、T3执行完最后执行主线程才结束? ...
  • 三个线程T1,T2,T3,如何保证顺序执行? 在多线程中有多种方法让线程按特定顺序执行,你可以用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。为了确保三个线程的顺序你应该先启动...
  • 如何让多线程顺序执行

    千次阅读 2020-09-03 16:27:25
    比如在线程thread2中,加上一句thread1.join(),其意义在于,当前线程2运行到此行代码时会进入阻塞状态,直到线程thread1执行完毕后,线程thread2才会继续运行,这就保证线程thread1与线程thread2的运行顺序 ...
  • 1.使用线程的join方法 public static void main(String[] args) { final Thread t1 = new Thread(new Runnable() { @Override public void run() { System.out.println("起床"); } }); final Thread t2
  • ABC三个线程如何保证顺序执行

    千次阅读 2021-03-10 03:06:59
    介绍最近看看多线程练习题,练习下多线程,这道题:ABC三个线程如何保证顺序执行。...初始版实现/*** @description A\B\C三个线程顺序执行10次** @author sunpy* @date 2018年11月28日 下午2:23:45...
  • 如何保证线程顺序执行完成?

    千次阅读 2021-03-10 02:59:19
    我们知道线程执行时机是CPU时间片轮询策略决定的,那么有没有办法让线程按指定的顺序执行呢?下面就通过JAVA提供的两种API来实现。1.首先定义三个线程对象,用来模拟多线程执行顺序。staticThreadthread1=newThread...
  • 如何确保三个线程顺序执行

    万次阅读 多人点赞 2018-07-03 09:42:00
    使用join thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。t.join(); //调用join方法,...
  • 笔者今天看到一个有趣的面试题,如何让多个线程按照既定的顺序依次执行?比如每个线程输出一个整数, 那么期望就是这样的:0,1,2,3,4,5,6,7,8,9.而不是0,2,4,1,3,5,8,7,9,6 乍一看,这不是反人性...
  • JUC之线程顺序执行 方式一:使用Thread中的join() ​ join() 用于不断让当前线程等待join线程之行结束。其原理就是不停的检查join线程是否存活,如果join线程存活则让当前线程影院等待。其中源码中wait(0)表示永远...
  • 题目描述:如何保证多个线程顺序执行? join方式实现 join方式即使用Thread.join方法来实现。Thread.join含义当前线程需要等待previousThread线程终止之后才从thread.join返回。简单来说,就是线程没有执行完...
  • 有三个线程 t1,t2,t3,怎么确保它们按顺序执行
  • 让多线程顺序执行的几种方法

    万次阅读 多人点赞 2019-09-05 14:23:58
    文章介绍4种方法,简单易懂,通过4个demo抛砖引玉。 目录 在子线程中通过join()方法指定顺序 在主线程中通过join()方法指定顺序 ...通过join()方法使当前线程“阻塞”,等待指定线程执行完毕后继续执行。举例:在...
  • 其中有一个问题是老掉牙 的怎么实现多线程顺序执行~ 首先要理解多线程的几个生命周期,当调用Thread的start()方法,不代表这个线程就立刻执行了,而是这个线程进入了就绪状态,要执行的话还需要由CPU调度才能进入...
  • 就是让线程thread执行完成后,再执行后面的代码逻辑。 实现原理: join方法内部的实现是synchronized + object.wait()方法,比如在主线程main中执行 t.join(); 主线程main会持有调用join方法的线程t的锁,join方法...
  • 题目要求:创建三个线程,每个线程分别打印ABC,并按照ABC的顺序执行十次 题目可以使用多种不同的方式解决,下面我们分别使用 Condition 等待唤醒机制、Semaphore 信号量、CountDownLatch 闭锁、Thread.join() 方法...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 360,978
精华内容 144,391
关键字:

如何保证线程顺序执行