Java 取消a";而";Android中的循环

Java 取消a";而";Android中的循环,java,android,while-loop,Java,Android,While Loop,首先,很抱歉这个标题不是很有描述性 我有下面的代码,它不能正常工作(或如我所愿) 尽管我调用了“Cancel()”,但这段时间还在继续 private boolean cancelled; private synchronized Bitmap renderBitmap(PatchInputStream pis){ File file = new File(Environment.getExternalStorageDirectory()+url);

首先,很抱歉这个标题不是很有描述性

我有下面的代码,它不能正常工作(或如我所愿)

尽管我调用了“Cancel()”,但这段时间还在继续

private boolean cancelled;

private synchronized Bitmap renderBitmap(PatchInputStream pis){
              File file = new File(Environment.getExternalStorageDirectory()+url);

              FileOutputStream fos=new FileOutputStream(file);
              byte buf[]=new byte[2000];
              int len;
              while((len=pis.read(buf))>0 && !isCancelled() ){
                  fos.write(buf,0,len);
              }
              fos.close();
              if (isCancelled()){
                cancelled=false;
                return null;
              }

              Bitmap bm = saveBitmapToFile(file);
              return bm;
}

public boolean isCancelled(){
    return cancelled;
}

public void Cancel(){
    cancelled=true;
}

这个代码怎么了?我遗漏了什么吗?

按照@mibolma的建议,对取消的实例变量使用
volatile
。这将确保没有线程使用该变量的缓存版本。如果这不起作用,您可以尝试以下建议:

您的
cancel()
方法可能未被调用,带有while循环的线程不允许调用该方法。使用该方法

使当前正在执行的线程对象暂时暂停并允许其他线程执行

在while循环中:

          while((len=pis.read(buf))>0 && !isCancelled() ){
              fos.write(buf,0,len);
              Thread.yield();
          }

至少代码有一个并发错误,可以通过将
取消
设置为volatile
来解决。否则,不能保证另一个线程看到新值。 (显然情况并非如此。)

另一种可能是没有调用cancel()方法。 (显然情况并非如此。)


还有一种可能性是在不同的对象实例上调用cancel()方法。尝试将
System.out.println(System.identityHashCode(this))
添加到cancel()方法和while循环中,看看它们是否打印相同的值。

好的,很明显的问题-您是从单独的线程调用
cancel()
[大写方法名称.错误!]吗?很明显的问题2-如果您是从单独的线程调用它,调用
Cancel
的方法是否也使用了
synchronized
?我看不出
while
循环有任何错误-是否确实要取消()是否在正确的对象上调用?作为同步的替代方法,您可以将volatile关键字添加到您的布尔值中。您是否可以显示您调用的代码取消?我不同意。。。我不认为Android的调度算法那么幼稚。相反,不能保证取消中的更改到达另一个线程,因为它没有同步。您可能会认为
write()
是I/O绑定的,并且最终会屈服,并且假设两个线程具有相同的优先级,您可能会假设写入数据的线程将被抢占。可能需要做的只是将取消的变量设置为
volatile
@mibollma不确定我是否理解“到达另一个线程”这是从两个不同线程访问的同一个变量。这里的同步问题是在设置时试图读取它。@据我所知,写入线程可能会缓存布尔值,直到他被迫同步为止。因此,在写入线程同步其缓存之前,读取线程将读取旧值。问题也可能出在调用cancel()的代码中。或者read()方法在等待更多输入时无限期阻塞。或者对错误的对象调用了cancel()方法。在cancel()方法和while循环的开头添加println()语句。即使在调用cancel()之后,while循环是否也会执行多次?请发布一个System.out.println();不输出任何内容。系统输出打印项次(取消);在取消的方法中打印“true”,在while循环中打印“false”。是的,while循环一直执行到完成它的工作。在cancel方法和while循环中,
System.out.println(this)
打印什么?假设toString()和hashCode()方法未被重写,则应打印类名和标识对象实例的数字。如果打印输出不同,则它们是不同的对象。它们是不同的对象!当我执行Cancel()时,我实际上是在对旧对象执行该操作,因为新对象仍在创建中。“renderBitmap”函数是构造函数的一部分,最多需要15秒。我通过将这些繁重的过程移出构造函数来解决它。