我希望有一个线程在被主线程中断时执行一些I / O工作,然后返回睡眠/等待状态,直到再次调用该中断为止。
因此,我想出了一个似乎不起作用的实现。代码段如下。
注意-这里的flag
是一个公共变量,可以通过主类中的线程类进行访问
// in the main function this is how I am calling it
if(!flag) {
thread.interrupt()
}
//this is how my thread class is implemented
class IOworkthread extends Thread {
@Override
public void run() {
while(true) {
try {
flag = false;
Thread.sleep(1000);
} catch (InterruptedException e) {
flag = true;
try {
// doing my I/O work
} catch (Exception e1) {
// print the exception message
}
}
}
}
}
在上面的代码段中,第二个try-catch块捕获了InterruptedException。这意味着第一和第二try-catch块都在捕获中断。但是我只调用了中断在第一个try-catch块期间发生。
您能帮我吗?
编辑 如果您认为可以为我的目标找到另一种解决方案,那么我将很高兴知道:)
答案 0 :(得分:0)
如果快速响应该标志很重要,则可以尝试以下操作:
export { default as App } from './App.js';
这应该做些不同,因为在捕获InterruptedException的catch块中,线程的中断标志被重置(在catch块的末尾)。
答案 1 :(得分:0)
听起来确实像生产者/消费者构造。您似乎有一种错误的解决方法,IO应该驱动算法。由于您在代码实际操作中保持非常抽象,因此我需要坚持下去。
因此,假设您的“分布式算法”适用于T
类型的数据;这意味着可以将其描述为Consumer<T>
(此接口中的方法名称为accept(T value)
)。由于它可以同时运行,因此您需要创建多个实例。通常使用ExecutorService
完成此操作。 Executors
类提供了一组不错的工厂方法来创建一个工厂方法,让我们使用Executors.newFixedThreadPool(parallelism)
。
您的“ IO”线程运行以为算法创建输入,这意味着它是Supplier<T>
。我们可以在Executors.newSingleThreadExecutor()
中运行它。
我们使用BlockingQueue<T>
连接这两个;这是一个FIFO集合。 IO线程放入元素,算法实例取出下一个可用的元素。
这使整个设置看起来像这样:
void run() {
int parallelism = 4; // or whatever
ExecutorService algorithmExecutor = Executors.newFixedThreadPool(parallelism);
ExecutorService ioExecutor = Executors.newSingleThreadExecutor();
// this queue will accept up to 4 elements
// this might need to be changed depending on performance of each
BlockingQueue<T> queue = new ArrayBlockingQueue<T>(parallelism);
ioExecutor.submit(new IoExecutor(queue));
// take element from queue
T nextElement = getNextElement(queue);
while (nextElement != null) {
algorithmExecutor.submit(() -> new AlgorithmInstance().accept(nextElement));
nextElement = getNextElement(queue);
if (nextElement == null) break;
}
// wait until algorithms have finished running and cleanup
algorithmExecutor.awaitTermination(Integer.MAX_VALUE, TimeUnit.YEARS);
algorithmExecutor.shutdown();
ioExecutor.shutdown(); // the io thread should have terminated by now already
}
T getNextElement(BlockingQueue<T> queue) {
int timeOut = 1; // adjust depending on your IO
T result = null;
while (true) {
try {
result = queue.poll(timeOut, TimeUnits.SECONDS);
} catch (TimeoutException e) {} // retry indefinetely, we will get a value eventually
}
return result;
}
现在,这实际上并不能回答您的问题,因为您想知道当IO线程可以继续读取数据时如何通知IO线程。
这是通过BlockingQueue<>
的限制实现的,该限制将在达到此限制后不再接受元素,这意味着IO线程可以继续读取并尝试放入元素。
abstract class IoExecutor<T> {
private final BlockingQueue<T> queue;
public IoExecutor(BlockingQueue<T> q) { queue = q; }
public void run() {
while (hasMoreData()) {
T data = readData();
// this will block if the queue is full, so IO will pause
queue.put(data);
}
// put null into queue
queue.put(null);
}
protected boolean hasMoreData();
protected abstract T readData();
}
因此,在运行时,您应该始终有4个线程在运行算法,并且队列中(最多)有4个项目在等待其中一个算法线程完成并提取它们。