【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!");
    }
}
目录
相关文章
|
14天前
|
Java 开发者
Java多线程编程中的常见误区与最佳实践####
本文深入剖析了Java多线程编程中开发者常遇到的几个典型误区,如对`start()`与`run()`方法的混淆使用、忽视线程安全问题、错误处理未同步的共享变量等,并针对这些问题提出了具体的解决方案和最佳实践。通过实例代码对比,直观展示了正确与错误的实现方式,旨在帮助读者构建更加健壮、高效的多线程应用程序。 ####
|
15天前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
5天前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
|
4天前
|
安全 Java 开发者
Java中的多线程编程:从基础到实践
本文深入探讨了Java多线程编程的核心概念和实践技巧,旨在帮助读者理解多线程的工作原理,掌握线程的创建、管理和同步机制。通过具体示例和最佳实践,本文展示了如何在Java应用中有效地利用多线程技术,提高程序性能和响应速度。
27 1
|
12天前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
|
13天前
|
Java 开发者
Java多线程编程的艺术与实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的技术文档,本文以实战为导向,通过生动的实例和详尽的代码解析,引领读者领略多线程编程的魅力,掌握其在提升应用性能、优化资源利用方面的关键作用。无论你是Java初学者还是有一定经验的开发者,本文都将为你打开多线程编程的新视角。 ####
|
12天前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
|
18天前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
44 9
|
15天前
|
安全 Java 开发者
Java多线程编程中的常见问题与解决方案
本文深入探讨了Java多线程编程中常见的问题,包括线程安全问题、死锁、竞态条件等,并提供了相应的解决策略。文章首先介绍了多线程的基础知识,随后详细分析了每个问题的产生原因和典型场景,最后提出了实用的解决方案,旨在帮助开发者提高多线程程序的稳定性和性能。
|
17天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin