Java 关于长时间的任务中断,我如何解决这个多任务场景?
好的,我在一次采访中被问到这个多线程问题。问题是这样的Java 关于长时间的任务中断,我如何解决这个多任务场景?,java,multithreading,Java,Multithreading,好的,我在一次采访中被问到这个多线程问题。问题是这样的 public class Job { static boolean interruptTask = false; private static class Mytask extends Thread{ @Override public void run() { while(!interruptTask){ //do some time
public class Job {
static boolean interruptTask = false;
private static class Mytask extends Thread{
@Override
public void run() {
while(!interruptTask){
//do some time consuming thing until interruption like looping over millions of times
}
}
}
public static void main(String[] args) throws InterruptedException {
Mytask t = new Mytask();
t.run();
Thread.sleep(1000);
interruptTask=true;
t.join();
System.out.println("end");
}
}
问题陈述
此代码段有什么问题,您将如何修复它。
我在这里发现了问题。我认为问题在于,即使我们在main函数中使interrupttask变量为true,它也不会中断线程。线程将继续执行,直到长时间的执行结束
但是我想不出解决这个问题的办法?我的意思是,我们有一些工具,比如等待,通知线程,但我不认为这些是我们可以在这里使用的东西。在这种情况下,解决这个特定问题的方法应该是什么
有人能帮我找出这个问题的解决办法吗?或者一些关于我应该如何着手解决问题的指导 与所讨论的变化相关地改变了答案 编辑后
private static class Mytask extends Thread{
public void run(){
while(true){
if(Thread.currentThread().isInterrupted()){
System.out.println("Thread Interrupted");
break;
}
//do stuff here
}
}
}
public static void main(String[] args) throws InterruptedException {
Mytask t = new Mytask();
t.start();
try{
Thread.sleep(1000);
}catch(InterruptedException e){
}
System.out.println("Interrupting now");
t.interrupt();
System.out.println("end after interruption");
}
一个简单的解决方案是确保“长时间运行”任务定期中断,以允许另一个线程设置中断标志。通常,这是通过在预定的时间间隔后“睡眠”一小段时间来完成的。您还希望能够对“长时间运行”的代码进行分段。下面是伪代码
// interruptTask should be declared like volatile boolean interruptTask
long interval = <in milliseconds>
long lastPause = <system time>
while(!interruptTask){
if (<time now> - lastPause > interval) {
sleep(pausePeriod);
lastPause = <system time>
} else {
... long running work increment (not do this a billion times)
}
}
//interruptTask应该像volatile boolean interruptTask一样声明
长间隔=
长最后暂停=
while(!interruptTask){
如果(-lastPause>interval){
睡眠(暂停期);
最后暂停=
}否则{
…长时间运行的工作增量(不是10亿次)
}
}
有两个问题:
t.run()
应该是t.start()
。否则,这两项任务都是在单线程中完成的interruptTask
应该是volatile
或者应该通过synchronized
getter/setter访问。否则,允许Java假设只有一个线程在使用该字段并优化:
while(!interruptTask){
// something
}
进入:
在您的代码中,启动MyTask时没有创建新线程,因此thread.sleep(1000)或interruptTask=true正在执行,因为while循环正在执行,因此您无法中断该循环。@Boristeider循环不在问题中,我添加它是为了表示耗时的任务。我将编辑这个问题。我认为这里更大的问题是
中断任务
上的竞争条件。这个字段是非易失性的,可以从多个未同步的线程访问。好吧,Java中的线程只有在合作时才能停止。你的任务必须是可中断的。您需要将任务拆分为多个块,并在处理之间选中一个标志。最好不要使用您自己的标志,而是使用已经存在的。@Banthar我同意interrupttask正在多线程非同步中使用。但我真的无法想象让它同步会做什么?我是说这里的比赛条件是什么意思?@Dude请帮自己一个忙,用Java阅读一下。这里有种族危险。这就是为什么我说应该使用中断API。但是,如果您不知道原子性/可见性,我强烈建议您在执行任何线程之前阅读!OP改变了这个问题。这个答案不再相关。“while(true)”循环将无限期地循环,永远不会退出@以前是的。这就是杜德节目中发生的事情。Java认为,interruptTask
永远不会更改,并将while循环优化为if+无限循环。假设interruptTask
没有从其他线程写入,这是一个有效的优化。不幸的是,Java无法判断这个假设是错误的。@Banthar不完全正确-这是一个过于简单化的假设。JVM将interruptTask
的值缓存在线程的本地缓存中。然后线程将看不到变量的更新值。但是剩下的是+1。这仍然不起作用。“结束”已打印,但背景任务从未完成。
if(!interruptTask){
while(true){
// something
}
}
public class Job {
static boolean interruptTask = false;
private static class Mytask extends Thread{
@Override
public void run() {
while(!interruptTask){
//do some time consuming thing until interruption like looping over millions of times
}
}
}
public static void main(String[] args) throws InterruptedException {
(new Mytask()).start();
Thread.sleep(1000);
interruptTask=true;
System.out.println("end");
}
}