MST

星途 面试题库

面试题:Java多线程环境下优雅终止线程的最佳实践

在一个复杂的Java多线程应用中,存在多个线程相互协作,如生产者 - 消费者模型、线程池等情况。请设计一个通用的、优雅的线程终止方案,确保在终止线程时,能够妥善处理未完成的任务、资源释放等问题,同时尽量减少对系统性能的影响。请详细说明设计思路,并给出关键代码示例。
12.1万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 使用volatile标志位:定义一个volatile类型的标志位,用于线程间通信,告知线程是否需要终止。
  2. 生产者 - 消费者模型处理:在生产者线程中,当标志位为终止状态时,不再生产新任务,并等待队列中的任务被消费完。消费者线程在处理完当前任务后,检查标志位,若为终止状态且任务队列为空,则终止。
  3. 线程池处理:使用ExecutorServiceshutdown()awaitTermination()方法。shutdown()方法启动有序关闭,不再接受新任务,但会继续执行已提交的任务。awaitTermination()方法等待所有任务执行完成或超时。
  4. 资源释放:在每个线程的终止逻辑中,确保释放线程持有的资源,如文件句柄、数据库连接等。

关键代码示例

  1. 生产者 - 消费者模型示例
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

class Producer implements Runnable {
    private final BlockingQueue<Integer> queue;
    private volatile boolean stop = false;

    public Producer(BlockingQueue<Integer> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        int i = 0;
        while (!stop) {
            try {
                queue.put(i++);
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        // 等待队列中的任务被消费完
        while (!queue.isEmpty()) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public void stopProducer() {
        stop = true;
    }
}

class Consumer implements Runnable {
    private final BlockingQueue<Integer> queue;
    private volatile boolean stop = false;

    public Consumer(BlockingQueue<Integer> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        while (!stop ||!queue.isEmpty()) {
            try {
                Integer item = queue.take();
                System.out.println("Consumed: " + item);
                Thread.sleep(200);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public void stopConsumer() {
        stop = true;
    }
}
  1. 线程池示例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ThreadPoolShutdownExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        // 提交任务
        for (int i = 0; i < 100; i++) {
            executorService.submit(() -> {
                // 模拟任务执行
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
        // 启动有序关闭
        executorService.shutdown();
        try {
            // 等待所有任务执行完成或超时
            if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
                if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                    System.err.println("Pool did not terminate");
                }
            }
        } catch (InterruptedException ie) {
            executorService.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}