如何打断线程上班然后上班后睡觉?

时间:2019-06-02 06:39:43

标签: java multithreading thread-sleep

我希望有一个线程在被主线程中断时执行一些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块期间发生。

您能帮我吗?

编辑 如果您认为可以为我的目标找到另一种解决方案,那么我将很高兴知道:)

2 个答案:

答案 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个项目在等待其中一个算法线程完成并提取它们。