【Java面试】确保线程顺序执行的实现方法

简介: 【Java面试】确保线程顺序执行的实现方法

1.Thread.join()

我们来看看在 Java 7 Concurrency Cookbook 中相关的描述(很清楚地说明了 join() 的作用):

Waiting for the finalization of a thread
In some situations, we will have to wait for the finalization of a thread. For example, we may have a program that will begin initializing the resources it needs before proceeding with the rest of the execution. We can run the initialization tasks as threads and wait for its finalization before continuing with the rest of the program. For this purpose, we can use the join() method of the Thread class. When we call this method using a thread object, it suspends the execution of the calling thread until the object called finishes its execution.
当我们调用某个线程的这个方法时,这个方法会挂起调用线程,直到被调用线程结束执行,调用线程才会继续执行。内部使用了wait方法,和sleep的区别是,sleep不会释放锁,而wait会释放锁。
public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new Runnable() {

            @Override
            public void run() {
                System.out
                        .println(Thread.currentThread().getId() + "running...");
            }
        });

        Thread thread2 = new Thread(new Runnable() {

            @Override
            public void run() {
                System.out
                        .println(Thread.currentThread().getId() + "running...");
            }
        });

        Thread thread3 = new Thread(new Runnable() {

            @Override
            public void run() {
                System.out
                        .println(Thread.currentThread().getId() + "running...");
            }
        });
        thread1.start();
        thread1.join();

        thread2.start();
        thread2.join();

        thread3.start();
        thread3.join();
        System.out.println("Main Thread exit!");
    }
}

主线程这种按照顺序调用了thread1、thread2、thread3,main thread存当了调用者的角色。

2.自定义实现串行执行器

import java.util.ArrayDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new Runnable() {

            @Override
            public void run() {
                System.out
                        .println(Thread.currentThread().getId() + "running...");
            }
        });

        Thread thread2 = new Thread(new Runnable() {

            @Override
            public void run() {
                System.out
                        .println(Thread.currentThread().getId() + "running...");
            }
        });

        Thread thread3 = new Thread(new Runnable() {

            @Override
            public void run() {
                System.out
                        .println(Thread.currentThread().getId() + "running...");
            }
        });

        SerialDefineExecutor defineExecutor = new SerialDefineExecutor();
        defineExecutor.execute(thread1);
        defineExecutor.execute(thread2);
        defineExecutor.execute(thread3);

        System.out.println("Main Thread exit!");
    }

    public static class SerialDefineExecutor implements Executor {
        ArrayDeque<Runnable> queue = new ArrayDeque<Runnable>();
        Runnable current = null;
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 5,
                TimeUnit.SECONDS, sPoolWorkQueue);
        private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(
                128);

        public SerialDefineExecutor() {
            threadPoolExecutor.allowCoreThreadTimeOut(true);
        }
        public synchronized void execute(Runnable runnable) {
            queue.offer(new Runnable() {

                @Override
                public void run() {
                    try {
                        runnable.run();
                    } finally {
                        next();
                    }
                }
            });
            if (current == null) {
                next();
            }
        }

        private synchronized void next() {
            if (!queue.isEmpty()) {
                current = queue.pop();
                threadPoolExecutor.execute(current);
            }
        }
    }
}

看过AsyncTask源码的各位,肯定看到过内部有这个串行执行器,保证内部线程的顺序执行,这里我们可以模仿写一个。

3.Thread.setPriority

设置线程优先级

public class Main {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new Runnable() {

            @Override
            public void run() {
                System.out
                        .println(Thread.currentThread().getId() + "running...");
            }
        });

        Thread thread2 = new Thread(new Runnable() {

            @Override
            public void run() {
                System.out
                        .println(Thread.currentThread().getId() + "running...");
            }
        });

        Thread thread3 = new Thread(new Runnable() {

            @Override
            public void run() {
                System.out
                        .println(Thread.currentThread().getId() + "running...");
            }
        });

        thread1.setPriority(1);
        thread2.setPriority(2);
        thread3.setPriority(3);
        thread1.start();
        thread2.start();
        thread3.start();
        System.out.println("Main Thread exit!");
    }
}
目录
相关文章
|
5天前
|
Java
【Java】Math、System、RunTime、BigDecimal类常用方法
【Java】Math、System、RunTime、BigDecimal类常用方法
|
3天前
|
存储 缓存 网络协议
复盘女朋友面试4个月的Java基础题
这篇文章是关于Java基础面试题的复盘,涵盖了HashMap原理、对象序列化作用等高频面试问题,并强调了Java基础知识的重要性。
复盘女朋友面试4个月的Java基础题
|
1天前
|
存储 Java
|
2天前
|
存储 Java
|
4天前
|
Dart API C语言
Dart ffi 使用问题之想在C/C++中创建异步线程来调用Dart方法,如何操作
Dart ffi 使用问题之想在C/C++中创建异步线程来调用Dart方法,如何操作
|
4天前
|
Java UED
基于SpringBoot自定义线程池实现多线程执行方法,以及多线程之间的协调和同步
这篇文章介绍了在SpringBoot项目中如何自定义线程池来实现多线程执行方法,并探讨了多线程之间的协调和同步问题,提供了相关的示例代码。
25 0
|
4天前
|
Java API
Java8 Lambda 设计和实现问题之在Java 8的Stream API中,parallel=false时collect方法是如何实现的
Java8 Lambda 设计和实现问题之在Java 8的Stream API中,parallel=false时collect方法是如何实现的
|
4天前
|
Java Spring 容器
Java SpringBoot 中,动态执行 bean 对象中的方法
Java SpringBoot 中,动态执行 bean 对象中的方法
14 0
|
3月前
|
存储 安全 Java
深入理解Java并发编程:线程安全与锁机制
【5月更文挑战第31天】在Java并发编程中,线程安全和锁机制是两个核心概念。本文将深入探讨这两个概念,包括它们的定义、实现方式以及在实际开发中的应用。通过对线程安全和锁机制的深入理解,可以帮助我们更好地解决并发编程中的问题,提高程序的性能和稳定性。
|
15天前
|
存储 安全 Java
解锁Java并发编程奥秘:深入剖析Synchronized关键字的同步机制与实现原理,让多线程安全如磐石般稳固!
【8月更文挑战第4天】Java并发编程中,Synchronized关键字是确保多线程环境下数据一致性与线程安全的基础机制。它可通过修饰实例方法、静态方法或代码块来控制对共享资源的独占访问。Synchronized基于Java对象头中的监视器锁实现,通过MonitorEnter/MonitorExit指令管理锁的获取与释放。示例展示了如何使用Synchronized修饰方法以实现线程间的同步,避免数据竞争。掌握其原理对编写高效安全的多线程程序极为关键。
37 1