面试题答案
一键面试实现思路
- 标志位控制:使用一个共享的标志位来通知所有线程需要停止。
- 线程安全:确保标志位的访问是线程安全的,例如使用
std::mutex
。 - 任务完成确认:每个线程在循环中检查标志位,在退出前确保当前网页抓取和数据保存完成。
关键代码片段(以C++为例)
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <atomic>
std::atomic<bool> stopFlag(false);
std::mutex mtx;
// 模拟抓取网页并保存数据的函数
void crawlWebPage(int pageId) {
while (!stopFlag) {
// 模拟抓取网页
std::cout << "Thread " << std::this_thread::get_id() << " is crawling page " << pageId << std::endl;
// 模拟保存数据
std::cout << "Thread " << std::this_thread::get_id() << " has saved data for page " << pageId << std::endl;
// 适当休眠以模拟实际工作
std::this_thread::sleep_for(std::chrono::seconds(1));
}
// 停止前确保处理完当前网页
std::cout << "Thread " << std::this_thread::get_id() << " is finishing up page " << pageId << std::endl;
}
int main() {
const int numThreads = 3;
std::vector<std::thread> threads;
// 创建并启动线程
for (int i = 0; i < numThreads; ++i) {
threads.emplace_back(crawlWebPage, i);
}
// 主线程等待一段时间,模拟其他工作
std::this_thread::sleep_for(std::chrono::seconds(5));
// 设置停止标志
stopFlag = true;
// 等待所有线程结束
for (auto& thread : threads) {
thread.join();
}
std::cout << "All threads have stopped." << std::endl;
return 0;
}
在上述代码中:
std::atomic<bool> stopFlag
用于控制线程停止,原子类型确保线程安全访问。crawlWebPage
函数模拟了网页抓取和数据保存工作,并在循环中检查stopFlag
。- 主线程等待一段时间后设置
stopFlag
,然后等待所有线程结束。
不同编程语言实现方式有所不同,但核心思路类似,如Java可使用volatile
关键字和Thread.join()
方法等。例如Java代码示例:
public class WebCrawler {
private static volatile boolean stopFlag = false;
// 模拟抓取网页并保存数据的方法
public static void crawlWebPage(int pageId) {
while (!stopFlag) {
// 模拟抓取网页
System.out.println(Thread.currentThread().getName() + " is crawling page " + pageId);
// 模拟保存数据
System.out.println(Thread.currentThread().getName() + " has saved data for page " + pageId);
// 适当休眠以模拟实际工作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 停止前确保处理完当前网页
System.out.println(Thread.currentThread().getName() + " is finishing up page " + pageId);
}
public static void main(String[] args) {
final int numThreads = 3;
Thread[] threads = new Thread[numThreads];
// 创建并启动线程
for (int i = 0; i < numThreads; ++i) {
threads[i] = new Thread(() -> crawlWebPage(i));
threads[i].start();
}
// 主线程等待一段时间,模拟其他工作
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 设置停止标志
stopFlag = true;
// 等待所有线程结束
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("All threads have stopped.");
}
}
在Java代码中,volatile
关键字保证stopFlag
的可见性,每个线程能及时获取其最新值。Thread.join()
方法用于等待线程执行完毕。