如何取消正在运行的任务并将其替换为同一线程上的新任务?

The*_*viv 4 java concurrency swing

我想取消正在运行的任务并将其替换为同一线程上的新任务。

在下面的代码中,我使用了一个单线程执行器来启动一个新任务并捕获一个Future代表它的。然后我用Future取消了任务。但是,任务并没有取消。

  1. 为什么我的代码不起作用?
  2. 如何取消正在运行的任务并将其替换为同一线程上的新任务?

示例代码:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

class Task implements Runnable {
    public void run() {
        System.out.println("New task started");
        int i = 0; while (true) i++;
    }
}

public class TaskLauncher extends JFrame {
    private JButton button = new JButton("Start new task");
    private ExecutorService executor = Executors.newSingleThreadExecutor();
    private Future<?> future;

    public TaskLauncher() {
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                if (future != null) future.cancel(true);
                future = executor.submit(new Task());
            }
        });

        add(button);

        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new TaskLauncher();
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

Sur*_*mar 5

只是在 Future 对象上调用取消不会导致任务停止。有关更多信息,请参阅 API 文档。还要检查这个SO Question,它显示了您必须如何编码您的任务,以便可以使用 Future 对象取消它。

像这样修改你的任务:

class Task implements Runnable {
    public void run() {
        System.out.println("New task started");
        int i = 0; 
        while (true) {
            i++;
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("Exiting gracefully");
                return;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 那是不正确的!您应该调用 isInterrupted() 方法 *not* intrrupted() 因为它会重置中断标志。我更喜欢将它写入 while,即 while (!Thread.isInterrupted()) 那么你可以避免上面的多个分支返回和条件检查...... (2认同)