这2天搞线程,写了不少测试,其中一些挺好玩,一时兴起,测试代码比需求写大了,真实需求中用不到,扔了可惜,就留个档,将来有用时不用重头再来。
第一个线程叫CutString,一直后台运行。
第二个线程SecondThread会启动第三个线程Thread3,Thread3会一直在后台运行直到SecondThread发送来关闭信号。
SecondThread会不定期发送一些字符串到CutString线程,并告知CutString线程将结果送给Thread3线程,CutString会计算它的哈希值(花一些时间的运算),完成后有结果后送入Thread3。
Thread3会找时间处理CutString线程的返回结果,并将结果通知SecondThread,SecondThread判断结果后如果需要可以关闭Thread3,并通知CutString不要送结果去Thread3了。
为了方便,安全.....主要是为了省去100万字啰嗦的理由,用了线程池。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
CutStringRunnable cutString = new CutStringRunnable();
Thread cutThread = new Thread(cutString);
cutThread.setDaemon(true);
cutThread.start();
SecondThreadRunnable secondThread = new SecondThreadRunnable(cutString);
Thread secondThreadThread = new Thread(secondThread);
secondThreadThread.start();
executor.execute(secondThreadThread);
executor.execute(cutThread);
}
static class CutStringRunnable implements Runnable {
private volatile boolean keepRunning = true;
private String result = "";
public void run() {
while (keepRunning) {
// 使用sleep模拟长时间的运算
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 计算结果的哈希值
result = "Hello World";
int resultHashCode = result.hashCode();
// 将结果送入Thread3
Thread3ResultQueue.getInstance().offer(resultHashCode);
}
}
public void stop() {
this.keepRunning = false;
}
}
static class SecondThreadRunnable implements Runnable {
private CutStringRunnable cutString;
private volatile boolean keepRunning = true;
public SecondThreadRunnable(CutStringRunnable cutString) {
this.cutString = cutString;
}
public void run() {
while (keepRunning) {
// 发送一些字符串到CutString线程
cutString.calculateHash("Some string");
// 从Thread3处获取结果并进行处理
Integer result = Thread3ResultQueue.getInstance().poll();
if (result != null) {
// 处理结果
}
// 判断是否需要关闭Thread3
if (needToStop()) {
stopThread3();
}
}
}
public void stop() {
this.keepRunning = false;
cutString.stop();
}
private boolean needToStop() {
// 判断是否需要关闭Thread3的标志
return false;
}
private void stopThread3() {
// 发送关闭Thread3的信号
}
}
static class Thread3Runnable implements Runnable {
private volatile boolean keepRunning = true;
public void run() {
while (keepRunning) {
// 从CutString处获取结果并进行处理
Integer result = Thread3ResultQueue.getInstance().poll();
if (result != null) {
// 处理结果
}
}
}
public void stop() {
this.keepRunning = false;
}
}
static class Thread3ResultQueue {
private static final Thread3ResultQueue instance = new Thread3ResultQueue();
private Queue<Integer> queue = new LinkedList<>();
private Thread3ResultQueue() {
}
public static Thread3ResultQueue getInstance() {
return instance;
}
public void offer(Integer result) {
synchronized (queue) {
queue.offer(result);
queue.notifyAll();
}
}
public Integer poll() {
synchronized (queue) {
while (queue.isEmpty()) {
try {
queue.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
return queue.poll();
}
}
}
}
解释一下代码:
- `CutStringRunnable` 类实现了 `Runnable` 接口,表示它可以被放到线程中执行。 `CutStringRunnable` 持续在后台运行,计算一个字符串的哈希值,然后将结果传递给 `Thread3` 线程, `Thread3ResultQueue` 是一个队列用于保存 `Thread3` 可以处理的结果。
- `SecondThreadRunnable` 类也实现了 `Runnable` 接口。它将 `CutStringRunnable` 作为参数传递进入构造函数中。它会定期向 `CutStringRunnable` 线程发送字符串并告诉它将结果送给 `Thread3Thread` 线程。 它还会从 `Thread3ResultQueue` 中获取结果并进行处理。如果需要关闭 `Thread3` ,则会发送一个关闭信号。
- `Thread3Runnable` 类也实现了 `Runnable` 接口。它持续运行在后台,从 `Thread3ResultQueue` 中获取结果并进行处理。如果需要关闭,则停止运行。
- `Thread3ResultQueue`类是一个线程安全的队列,用于保存 `Thread3` 可以处理的结果。如果队列为空,调用 `poll()` 方法的线程会被阻塞,直到从另一个线程中调用 `offer()` 方法将结果添加到队列中。
在 `main` 方法中,我们使用 `Executors.newFixedThreadPool()` 方法创建了一个线程池,该线程池包含三个线程。后面我们将 `SecondThreadRunnable` 和 `CutStringRunnable` 分别作为任务提交到线程池中执行。开发过程中,可能需要根据具体情况调整线程池的大小。