Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/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_Android_Multithreading - Fatal编程技术网

Java 即使在调用中断方法之后,线程也不会被中断

Java 即使在调用中断方法之后,线程也不会被中断,java,android,multithreading,Java,Android,Multithreading,我有一个带有3个按钮的活动:创建、开始和取消。Button create创建一个新线程,Button start运行该线程,Button cancel停止该线程。我的问题是,调用中断方法后线程并没有中断。这个操作是在单击取消按钮后执行的。我知道,在我的线程中,我应该检查线程是否被中断。我添加了它,但中断仍然不起作用。这是我的密码: private View.OnClickListener listener = new View.OnClickListener() { @Suppr

我有一个带有3个按钮的活动:创建、开始和取消。Button create创建一个新线程,Button start运行该线程,Button cancel停止该线程。我的问题是,调用中断方法后线程并没有中断。这个操作是在单击取消按钮后执行的。我知道,在我的线程中,我应该检查线程是否被中断。我添加了它,但中断仍然不起作用。这是我的密码:

private View.OnClickListener listener = new View.OnClickListener() {
        @SuppressLint("HandlerLeak")
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.create_button:
                    thread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            int i;
                            for (i = 0; i<10;i++){
                                final int finalI = i;
                                new Handler().postDelayed(new Runnable() {
                                    @Override
                                    public void run() {
                                        textCounter.post(new Runnable() {
                                            @Override
                                            public void run() {
                                                textCounter.setText(String.valueOf(finalI));
                                            }
                                        });
                                    }
                                }, 500*i);
                                if (thread.isInterrupted()){
                                    Log.i(getClass().getSimpleName(), "Thread is interrupted");
                                    return;
                                }
                            }
                            new Handler().postDelayed(new Runnable() {
                                @SuppressLint("SetTextI18n")
                                @Override
                                public void run() {
                                    textCounter.setText("Done!");
                                }
                            },(i+1)*500);
                        }
                    });

                    break;
                case R.id.start_button:
                    thread.run();
                    break;
                case R.id.cancel_button:
                    thread.interrupt();
                    Log.i(getClass().getSimpleName(), "Cancel Button clicked");
                    break;
            }
        }
    };

那么,为什么线程没有被中断,我如何解决这个问题呢?

您的线程正在快速添加11个任务10+最后一个任务到您正在创建的处理程序中,然后死亡。这些任务有一个延迟,然后消息队列将负责运行10+1可运行程序。要执行您试图执行的操作,应该使线程在每个循环之间等待500毫秒

类似于此:

                thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        int i;
                        for (i = 0; i<10;i++){
                            final int finalI = i;
                            textCounter.post(new Runnable() {
                                @Override
                                public void run() {
                                    textCounter.setText(String.valueOf(finalI));
                                }
                            });
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException ignored) {
                                Log.i(getClass().getSimpleName(), "Thread is interrupted");
                                return;
                            }
                            if (thread.isInterrupted()){
                                Log.i(getClass().getSimpleName(), "Thread is interrupted");
                                return;
                            }
                        }
                        textCounter.post(new Runnable() {
                            @Override
                            public void run() {
                                textCounter.setText("Done!");
                            }
                        });
                    }
                });

您的线程正在快速添加11个任务,10+最后一个任务到您正在创建的处理程序中,然后死亡。这些任务有一个延迟,然后消息队列将负责运行10+1可运行程序。要执行您试图执行的操作,应该使线程在每个循环之间等待500毫秒

类似于此:

                thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        int i;
                        for (i = 0; i<10;i++){
                            final int finalI = i;
                            textCounter.post(new Runnable() {
                                @Override
                                public void run() {
                                    textCounter.setText(String.valueOf(finalI));
                                }
                            });
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException ignored) {
                                Log.i(getClass().getSimpleName(), "Thread is interrupted");
                                return;
                            }
                            if (thread.isInterrupted()){
                                Log.i(getClass().getSimpleName(), "Thread is interrupted");
                                return;
                            }
                        }
                        textCounter.post(new Runnable() {
                            @Override
                            public void run() {
                                textCounter.setText("Done!");
                            }
                        });
                    }
                });

你的代码有很多问题

问题1:当用户单击“创建”按钮时,您创建了一个新线程,这不是您想要的预期行为,因此,如果尚未创建或终止新线程,只需创建一个新线程即可

问题2:当用户单击开始按钮时

此行并不启动线程,它只是在调用线程的run方法中执行代码,在本例中是main/UI线程。要启动线程,必须使用start方法。如果线程已创建,请确保启动该线程

问题3:当用户单击“取消”按钮时

因为没有线程启动,所以此行将不执行任何操作

问题4:根据您的描述,您希望使用线程将TextView上的计数器每0.5秒从0增加到9,然后显示“完成”。您的代码不正确,并且包含许多冗余代码

解决方案:您可以遵循以下代码

private View.OnClickListener listener = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.create_button:
                // Only create a new thread if it is not created or it is terminated.
                if (thread == null || thread.getState() == Thread.State.TERMINATED) {
                    thread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                for (int i = 0; i < 10; i++) {
                                    final int finalI = i;

                                    // This will post a message to main/UI thread.
                                    textCounter.post(new Runnable() {
                                        @Override
                                        public void run() {
                                            textCounter.setText(String.valueOf(finalI));
                                        }
                                    });

                                    // Sleep current thread in 0.5 second before running next step.
                                    Thread.sleep(500);
                                }

                                // Display Done after finishing counter.
                                textCounter.post(new Runnable() {
                                    @SuppressLint("SetTextI18n")
                                    @Override
                                    public void run() {
                                        textCounter.setText("Done!");
                                    }
                                });
                            } catch (InterruptedException e) {
                                // Display Cancelled if the current thread is cancelled.
                                textCounter.post(new Runnable() {
                                    @SuppressLint("SetTextI18n")
                                    @Override
                                    public void run() {
                                        textCounter.setText("Cancelled!");
                                    }
                                });
                            }
                        }
                    });
                } else {
                    Toast.makeText(MainActivity.this,
                            "Thread is already created. No need to create anymore.",
                            Toast.LENGTH_SHORT)
                            .show();
                }
                break;
            case R.id.start_button:
                // Start thread if it is created.
                if (thread != null && thread.getState() == Thread.State.NEW) {
                    thread.start();
                } else {
                    Toast.makeText(MainActivity.this,
                            "Thread is not created yet or it is running.",
                            Toast.LENGTH_SHORT)
                            .show();
                }
                break;
            case R.id.cancel_button:
                // Cancel the thread if it is running.
                if (thread != null && thread.isAlive()) {
                    thread.interrupt();
                } else {
                    Toast.makeText(MainActivity.this,
                            "Thread is not running yet.",
                            Toast.LENGTH_SHORT)
                            .show();
                }
                break;
        }
    }
};

你的代码有很多问题

问题1:当用户单击“创建”按钮时,您创建了一个新线程,这不是您想要的预期行为,因此,如果尚未创建或终止新线程,只需创建一个新线程即可

问题2:当用户单击开始按钮时

此行并不启动线程,它只是在调用线程的run方法中执行代码,在本例中是main/UI线程。要启动线程,必须使用start方法。如果线程已创建,请确保启动该线程

问题3:当用户单击“取消”按钮时

因为没有线程启动,所以此行将不执行任何操作

问题4:根据您的描述,您希望使用线程将TextView上的计数器每0.5秒从0增加到9,然后显示“完成”。您的代码不正确,并且包含许多冗余代码

解决方案:您可以遵循以下代码

private View.OnClickListener listener = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.create_button:
                // Only create a new thread if it is not created or it is terminated.
                if (thread == null || thread.getState() == Thread.State.TERMINATED) {
                    thread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                for (int i = 0; i < 10; i++) {
                                    final int finalI = i;

                                    // This will post a message to main/UI thread.
                                    textCounter.post(new Runnable() {
                                        @Override
                                        public void run() {
                                            textCounter.setText(String.valueOf(finalI));
                                        }
                                    });

                                    // Sleep current thread in 0.5 second before running next step.
                                    Thread.sleep(500);
                                }

                                // Display Done after finishing counter.
                                textCounter.post(new Runnable() {
                                    @SuppressLint("SetTextI18n")
                                    @Override
                                    public void run() {
                                        textCounter.setText("Done!");
                                    }
                                });
                            } catch (InterruptedException e) {
                                // Display Cancelled if the current thread is cancelled.
                                textCounter.post(new Runnable() {
                                    @SuppressLint("SetTextI18n")
                                    @Override
                                    public void run() {
                                        textCounter.setText("Cancelled!");
                                    }
                                });
                            }
                        }
                    });
                } else {
                    Toast.makeText(MainActivity.this,
                            "Thread is already created. No need to create anymore.",
                            Toast.LENGTH_SHORT)
                            .show();
                }
                break;
            case R.id.start_button:
                // Start thread if it is created.
                if (thread != null && thread.getState() == Thread.State.NEW) {
                    thread.start();
                } else {
                    Toast.makeText(MainActivity.this,
                            "Thread is not created yet or it is running.",
                            Toast.LENGTH_SHORT)
                            .show();
                }
                break;
            case R.id.cancel_button:
                // Cancel the thread if it is running.
                if (thread != null && thread.isAlive()) {
                    thread.interrupt();
                } else {
                    Toast.makeText(MainActivity.this,
                            "Thread is not running yet.",
                            Toast.LENGTH_SHORT)
                            .show();
                }
                break;
        }
    }
};

为什么要投否决票?即使这段代码很难看,但基本上是在做问题作者所问的事情。当然,有更好的方法可以做到这一点。这是正确的答案,我只想补充一点,isInterrupted返回false,因为线程在终止后很久就被中断了,在这种情况下,isInterrupted的设计行为是返回false。为什么要投否决票?即使这段代码很难看,但基本上是在做问题作者所问的事情。当然,还有更好的方法。这是正确的答案,我只想补充一点,isInterrupted返回false,因为线程在终止后很久就被中断了,在这种情况下,isInterrupted的设计行为,是返回false。@XavierRubioJansana正确识别了您的问题-作为他的解决方案的替代方案,您还可以通过调用其RemoveCallback来取消任何未完成的延迟处理程序。为此,您需要在cancel案例中引用每个处理程序。查看并遵循该答案中的任何链接。@XavierRubioJansana正确识别了您的问题-作为他的解决方案的替代方案,您还可以通过调用其RemoveCallback来取消任何未完成的延迟处理程序。为此,您需要在cancel案例中引用每个处理程序。查看并遵循该答案中的任何链接。没有注意到问题2,捕捉良好。我专注于延迟的问题,最终没有注意到。顺便说一句@sergei mikhailovskii这是线程的一个非常常见的错误。另外,全局try-catch(而不是同时检查isInterrupted和捕获异常)似乎是一个很好的折衷方法,可以简化一点代码。我专注于延迟的问题,最终没有注意到。顺便说一句@sergei mikhailovskii这是线程的一个非常常见的错误。另外,一个全局try-catch(而不是同时检查isInterrupted和捕获异常)看起来像 这里有一个很好的例子,可以简化一点代码。