线程不会死,并且其中两个保持重叠

时间:2019-10-05 11:56:21

标签: java multithreading

我需要一个线程一次只能运行一次,例如,如果它是第一次调用它将运行,如果它是第二次调用,则第一个应该完全停止并被允许死亡,并且一个新的一个应该取代它的地方。 我进行了一次小测试,以查看每次执行之间实际发生的情况,结果表明该线程没有消失,但是两个线程并排执行:

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();
                }
            }
        }
    }
}

结果如下:

//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)代替布尔标志,得到了相同的结果。 如何正确停止“线程4”并仅运行其中之一?

实际的问题来自于一个线程,该线程将循环遍历列表并根据请求更新不和谐聊天中的内容,该线程的作用是按照肾脏的建议监听输入并进行更改,我正在尝试使用executor.submit()和未来

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时进行初始化?

2 个答案:

答案 0 :(得分:1)

似乎valid方法可以同时被调用多次。这意味着,这些调用中的每个调用都将只等待一个线程(Worker)结束,而每个调用都创建自己的Worker,并且您丢失了指向它的指针,因此无法停止一堆新创建的worker 。 您应该使valid方法同步:synchronized void valid(),这将阻止创建许多工作程序:

@Override
synchronized public void valid() {
    ...
}

还有话要说。您将while循环放在try-catch之外,这是错误的:如果胎面被打断,则打断不会杀死它,因为下一个中断开始了,所以应该像这样:

@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 :(得分:1)

我使用single thread executor service,尝试这样的事情:

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