Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 中断未知线程_Java_Multithreading - Fatal编程技术网

Java 中断未知线程

Java 中断未知线程,java,multithreading,Java,Multithreading,考虑以下(简化的)类,该类旨在允许我的整个组件在完全停止之前进入某种临时状态(临时状态的目的是允许组件完成其现有任务,但拒绝任何新任务) 可以从任意数量的线程多次启动和停止组件 class StopHandler { boolean isStarted = false; synchronized void start() {isStarted = true;} //synchronized as I do want the client code to block u

考虑以下(简化的)类,该类旨在允许我的整个组件在完全停止之前进入某种临时状态
(临时状态的目的是允许组件完成其现有任务,但拒绝任何新任务)
可以从任意数量的线程多次启动和停止组件

class StopHandler {
    boolean isStarted = false;

    synchronized void start() {isStarted = true;}

    //synchronized as I do want the client code to block until the component is stopped.
    //I might add some async method as well, but let's concentrate on the sync version only.
    synchronized void stop(boolean isUrgent) {
        if (isStarted) {
            if (!isUrgent) {
                setGlobalState(PREPARING_TO_STOP); //assume it is implemented
                try {Thread.sleep(10_000L);} catch (InterruptedException ignored) {}
            }
            isStarted = false;
    }
}
当前实现的问题是,如果某些客户端代码需要在组件处于过渡状态时紧急停止组件,那么它仍然需要等待
例如:

//one thread
stopHandler.stop(false); //not urgent => it is sleeping
//another thread, after 1 millisecond:
stopHandler.stop(true); //it's urgent, "please stop now", but it will wait for 10 seconds
您将如何实施它

我可能需要中断休眠线程,但我没有可调用“interrupt()”的休眠线程对象。

在调用sleep之前直接在StopHandler的字段中存储对当前线程(由thread.currentThread()返回)的引用如何?这将允许您在随后的紧急调用中中断它,以防线程仍然处于活动状态。

找不到比Lars建议的更好的解决方案。 只需要封装睡眠管理就可以了

class SleepHandler {
        private final ReentrantLock sleepingThreadLock;
        private volatile Thread sleepingThread;

        SleepHandler() {
            sleepingThreadLock = new ReentrantLock();
        }

        void sleep(long millis) throws InterruptedException {
            setSleepingThread(Thread.currentThread());
            Thread.sleep(millis);
            setSleepingThread(null);
        }

        void interruptIfSleeping() {
            doWithinSleepingThreadLock(() -> {
                if (sleepingThread != null) {
                    sleepingThread.interrupt();
                }
            });
        }

        private void setSleepingThread(@Nullable Thread sleepingThread) {
            doWithinSleepingThreadLock(() -> this.sleepingThread = sleepingThread);
        }

        private void doWithinSleepingThreadLock(Runnable runnable) {
            sleepingThreadLock.lock();
            try {
                runnable.run();
            } finally {
                sleepingThreadLock.unlock();
            }
        }
    }
使用此帮助器类,原始问题的处理非常简单:

void stop(boolean isUrgent) throws InterruptedException {
    if (isUrgent) {sleepHandler.interruptIfSleeping();} //harmless if not sleeping
    try {
        doStop(isUrgent); //all the stuff in the original 'stop(...)' method
    } catch (InteruptedException ignored) {
    } finally {
        Thread.interrupted(); //just in case, clearing the 'interrupt' flag as no need to propagate it futher
    }

为什么在这里使用同步方法?由于没有为
isStarted
变量获取参数,即使我调用它10次,我也知道最后的结果是什么
isStarted=false
顺便说一句,您可能希望在睡眠后更改状态(睡眠后不是准备停止,而是停止),因为如果您从不同线程调用它10次,您希望它们一个接一个地发生。使用'isUrgent=false'应该需要100秒。如果您试图在它停止的过程中启动它,它也应该等待。因此,启动
isStart
false
需要100秒?然后您会遇到一个问题,因为第一个“none-urgent”调用将在10秒后更改该值,并且由于第一个条件为false,以下线程将不会执行任何操作。如果您只想在每次等待呼叫完成时更改值,则始终可以同步“none Emergency”块并管理等待队列。对不起,我的意思是开始()、停止(false)、开始()、停止(false)等10次。虽然通话几乎是同时进行的,但这应该需要大约100秒(可能更少)。这可能会起作用,但似乎有点“太手动”。我想可能有人会建议使用不同的java并发结构,比如闩锁等。无论如何,这是个好主意