首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程不会死,它们中的两个保持重叠

线程不会死,它们中的两个保持重叠
EN

Stack Overflow用户
提问于 2019-10-05 19:56:22
回答 2查看 255关注 0票数 1

我需要一个一次只运行一次的线程,例如,如果它是第一次被调用,它将运行,如果它被第二次调用,第一个线程应该完全停止并被允许死亡,一个新的线程应该取代它的位置。我运行了一个小测试,看看每次执行之间实际发生了什么,结果显示线程并没有死,而是有两个线程同时执行:

代码语言:javascript
复制
public class Test {
    Worker worker = new Worker();

    @Override
    public void valid() {

        try {
            if (worker.running) {
                worker.running = false;
                worker.join();
            }

        } catch (InterruptedException iex) {
            worker.running = false;
        }

        worker = new Worker();

        worker.start();

    }

    private final class Worker extends Thread {
        private volatile boolean running = true;

        @Override
        public void run() {
            while (running) {
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException iex) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
}

结果如下:

代码语言:javascript
复制
//Upon first execution
Thread-4
Thread-4
Thread-4
Thread-4

//When I execute it again
Thread-7
Thread-4
Thread-7
Thread-4
Thread-7
Thread-4

我尝试过使用ExecutorServicewhile(!Thread.currentThread.isInterrupted)而不是boolean标志,也得到了同样的结果。我怎样才能正确地停止"Thread-4“并且只运行其中的一个?

实际的问题来自一个线程,该线程将循环通过列表并按请求更新不一致聊天中的内容,该线程所做的是侦听输入和更改,正如我尝试使用executor.submit()和Future所建议的那样

代码语言:javascript
复制
private ExecutorService executor = Executors.newSingleThreadExecutor();

    private Future<Void> worker;

    private void setupImageThread() {

        if (!worker.isDone() && !worker.isCancelled()) {
            worker.cancel(true);
        }

        this.worker = (Future<Void>)executor.submit(new Cycler(Listener.queue(), this.links, Cel.cMember()));

        ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);

        Runnable timeout = () -> {

            executor.shutdown();

        };

        ses.schedule(timeout, 100, TimeUnit.SECONDS);
    }

第一次创建Future时,我该如何开始初始化它?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-05 20:34:55

使用single thread executor service时,我会尝试如下所示:

代码语言:javascript
复制
public class Test {

    private static ExecutorService executor = Executors.newSingleThreadExecutor();

    Future<Void> worker;

    public Test() {
        this.worker = executor.submit(new Worker());
    }

    @Override
    public void valid() {
        if (!worker.isDone() && !worker.isCancelled()) {
            worker.cancel(true);  // Depends on whether you want to interrupt or not
        }

        this.worker = executor.submit(new Worker());
    }
}

并使Worker实现Runnable

票数 1
EN

Stack Overflow用户

发布于 2019-10-05 20:31:25

看起来valid方法可以同时调用几次。这意味着,这些调用中的每一个都将等待一个线程(Worker)的结束,而每个调用都创建了自己的Worker,而您丢失了一个指向它的指针,因此不可能停止一堆新创建的Worker。您应该使valid方法同步:synchronized void valid()它将防止创建许多工作进程:

代码语言:javascript
复制
@Override
synchronized public void valid() {
    ...
}

还有一件事要说。您将while循环放在try-catch之外,这是错误的:如果踏步被中断,中断不会杀死它,因为下一次迭代将开始,所以应该是这样的:

代码语言:javascript
复制
@Override
public void run() {
    try {
        while (running) {
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(2000);
        }
    catch (InterruptedException iex) {
       //you don't need here Thread.currentThread().interrupt() call, because the thread has alredy been interrupted. 
       // The return statement here is also obsolete, I just use it as an example, but you can use empty braces.
       return; 
    }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58248059

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档