首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不能让Thread.interrupt工作

不能让Thread.interrupt工作
EN

Stack Overflow用户
提问于 2018-01-10 00:48:34
回答 1查看 61关注 0票数 2

我有一个程序,执行一些文件I/O,然后睡几秒钟,检查文件是否已经改变,然后睡觉,如果它们是一样的。如果它们已经更改,则执行相同的文件I/O,然后返回休眠状态。我想要实现一个击键,如果按下这个线程,它会唤醒这个线程,但是我无法让这个线程处理InterruptedException。我的(简化)代码在这里:

代码语言:javascript
复制
import java.awt.Color;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class StackOverFlowExample extends JFrame{

    private class MyDispatcher implements KeyEventDispatcher {
        boolean keyEventDone = false;

        @Override
        public boolean dispatchKeyEvent(KeyEvent e) {
            if(e.getID() == KeyEvent.KEY_PRESSED){
                if((e.getKeyCode() == 80 && e.getModifiers() == 11) && !keyEventDone){
                    System.out.println("interrupting");
                    interrupt();
                }
            }
            if (e.getID() == KeyEvent.KEY_RELEASED) {
                if(e.getKeyCode() == 80){
                    keyEventDone = false;
                }
            }
            return true;
        }

    }

public void interrupt(){
    System.out.println("recieved interrupt");
    Thread.currentThread().interrupt();
}

public static void main(String[] args){
    String fileName = "file Name";
    String oldFileName = "oldFileName";
    JFrame frame = new StackOverFlowExample();
    frame.setUndecorated(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
    frame.setSize(217, 104);

    do{
        if(!fileName.equals(oldFileName)){

        }else{
            try {
                System.out.println("Same file");
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                System.out.println("continuing");
                if(Thread.currentThread().isInterrupted()){
                    System.out.println("continuing");
                    continue;
                }
                e.printStackTrace();
            }
        }
        oldFileName = fileName;
    }while(true);

}
public StackOverFlowExample(){
    super("");
    JPanel pane = new JPanel();
    pane.setBackground(Color.LIGHT_GRAY);
    setContentPane(pane);
    KeyboardFocusManager manager = 
    KeyboardFocusManager.getCurrentKeyboardFocusManager();
manager.addKeyEventDispatcher(new MyDispatcher());
}

}

类中还有其他东西,但这些都与线程或其他任何东西无关。而且,我知道检查文件名并不是最好的方法,但是在我的应用程序中,如果文件名不同,则文件名总是不同的,因为文件名是根据时间生成的。

当我按下"ctrl+shift+alt+p“来唤醒线程时,它会从MyDispatcher类中打印出”中断“,并从主类的中断方法中输出”接收中断“,但是没有其他东西,线程只是一直在休眠。

我看到的中断休眠线程的所有示例都有线程,而不是主类中的线程。这就是我的不工作的原因吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-10 01:40:34

再次,您打断了错误的线程,并希望传递正确的线程。例如,获取您的代码:

代码语言:javascript
复制
import java.awt.Color;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class StackOverFlowExample extends JFrame {
    static String oldFileName = "oldFileName";
    private Thread runningThread;

    private class MyDispatcher implements KeyEventDispatcher {
        boolean keyEventDone = false;

        @Override
        public boolean dispatchKeyEvent(KeyEvent e) {
            if (e.getID() == KeyEvent.KEY_PRESSED) {
                if ((e.getKeyCode() == 80 && e.getModifiers() == 11) && !keyEventDone) {
                    System.out.println("interrupting");
                    interrupt();
                }
            }
            if (e.getID() == KeyEvent.KEY_RELEASED) {
                if (e.getKeyCode() == 80) {
                    keyEventDone = false;
                }
            }
            return true;
        }

    }

    // pass in the correct thread to interrupt
    public void setRunningThread(Thread runningThread) {
        this.runningThread = runningThread;
    }

    public void interrupt() {
        System.out.println("recieved interrupt");
        // !! Thread.currentThread().interrupt();
        runningThread.interrupt();
        System.out.println("interrupt Thread id: " + Thread.currentThread().getId());
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            String fileName = "file Name";
            StackOverFlowExample frame = new StackOverFlowExample();
            frame.setUndecorated(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setVisible(true);
            frame.setSize(217, 104);

            Thread thread = new Thread(() -> {
                do {
                    if (!fileName.equals(oldFileName)) {

                    } else {
                        try {
                            System.out.println("do-while Thread id: " + Thread.currentThread().getId());

                            System.out.println("Same file");
                            Thread.sleep(10000);
                        } catch (InterruptedException e) {
                            System.out.println("continuing");
                            if (Thread.currentThread().isInterrupted()) {
                                System.out.println("continuing");
                                continue;
                            }
                            e.printStackTrace();
                        }
                    }
                    oldFileName = fileName;
                } while (true);
            });

            // pass in the thread
            frame.setRunningThread(thread);
            thread.start(); // start it running
        });
    }

    public StackOverFlowExample() {
        super("");
        JPanel pane = new JPanel();
        pane.setBackground(Color.LIGHT_GRAY);
        setContentPane(pane);
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.addKeyEventDispatcher(new MyDispatcher());
    }

}

也许是一种简单的方法来做你想做的事:

  • 创建一个每x秒重复一次的Swing计时器(在本例中我们将使用10秒)
  • 在计时器内部启动一个新线程,如果我们需要它来更直接地与GUI交互,可以启动一个SwingWorker,它检查文件的情况,并在需要时执行文件I/O。
  • 给计时器初始延迟为0,以便它立即启动或重新启动。
  • 使用键绑定而不是烦躁的KeyListener
  • 在由我们的绑定触发的操作中,只需在Swing计时器上调用restart(),因为初始延迟为0,它立即重新启动其操作,然后重新启动10秒等待。

类似于:

代码语言:javascript
复制
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class StackOverflowExample2 extends JPanel {
    // 10 seconds between tasks
    private static final int TIMER_DELAY = 10 * 1000;
    int keyCode = KeyEvent.VK_P;
    int modifiers = InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK
            | InputEvent.ALT_DOWN_MASK;
    private KeyStroke shftCtrlAltP = KeyStroke.getKeyStroke(keyCode, modifiers);
    private int condition = WHEN_IN_FOCUSED_WINDOW;
    private InputMap inputMap = getInputMap(condition);
    private ActionMap actionMap = getActionMap();
    private Timer myTimer = new Timer(TIMER_DELAY, new TimerListener());

    public StackOverflowExample2() {
        setPreferredSize(new Dimension(400, 300));

        // create key binding
        inputMap.put(shftCtrlAltP, shftCtrlAltP.toString());
        actionMap.put(shftCtrlAltP.toString(), new MyAction());
        // myWorker.execute();
        myTimer.setInitialDelay(0);
        myTimer.start();
    }

    private class MyAction extends AbstractAction {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Key pressed");
            myTimer.restart(); // simply re-start the timer
        }
    }

    private class TimerListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // launch SwingWorker or other thread to check if files have changed
            // and if so do file I/O
            System.out.println("Timer running");
        }
    }

    private static void createAndShowGui() {
        StackOverflowExample2 mainPanel = new StackOverflowExample2();

        JFrame frame = new JFrame("StackOverflowExample2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

此外,您的代码和程序设计当前要求轮询一个文件或多个文件的状态,然后在它们更改时执行一些操作。一个更有效的选择是,根本不进行投票,而是使用Java API,这是自Java7以来核心Java的一部分。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48178791

复制
相关文章

相似问题

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