Java 线程:启动、挂起、恢复
我正在制作一个Android应用程序(min SDK:8,target SDK:19) 现在,我想设置一个加载图标,使其在应用程序检查internet连接之前显示 到现在为止我没有问题 我让这个方法为我做:Java 线程:启动、挂起、恢复,java,android,multithreading,Java,Android,Multithreading,我正在制作一个Android应用程序(min SDK:8,target SDK:19) 现在,我想设置一个加载图标,使其在应用程序检查internet连接之前显示 到现在为止我没有问题 我让这个方法为我做: void setLoader(boolean T, String msg){ View LAY = findViewById(R.id.loaderLayout); TextView MTV = (TextView) findViewById(R.id.loader_msg)
void setLoader(boolean T, String msg){
View LAY = findViewById(R.id.loaderLayout);
TextView MTV = (TextView) findViewById(R.id.loader_msg);
if(T && !loaderStarted){
loader.start();
LAY.setVisibility(View.VISIBLE);
MTV.setText(msg);
loaderStarted = true;
}
else if (!T && loaderStarted) {
loader.interrupt();
LAY.setVisibility(View.GONE);
loaderStarted = false;
}
}
然后我需要获取user&pass,然后再次用该线程锁定UI,以检查user&pass
问题是:
我在暂停线程时遇到问题:|
我的主要编程语言不是java
所以请帮我,我有这样的线索:
//first make loading icon visible then call :
final private Thread loader = new Thread(new Runnable(){
@Override
public void run() {
int i = 0;
while (true){
if(loader.isInterrupted()){
return;
}
try {Thread.sleep(25);} catch (InterruptedException e) {}
final int j = i;
runOnUiThread(new Runnable(){
public void run() {
ImageView imageView = (ImageView) findViewById(R.id.loaderImage);
Matrix matrix = new Matrix();
imageView.setScaleType(ScaleType.MATRIX);
int newWIDTH = imageView.getWidth();
int newHIEGHT = imageView.getHeight();
matrix.postScale(((float)(newWIDTH))/imageView.getDrawable().getBounds().width(), ((float)(newHIEGHT))/imageView.getDrawable().getBounds().height());
matrix.postRotate((float) j, newWIDTH/2, newHIEGHT/2);
imageView.setImageMatrix(matrix);
}
});
i = (i + 15) % 360;
}
}
});
void setLoader(boolean T, String msg){
View LAY = findViewById(R.id.loaderLayout);
TextView MTV = (TextView) findViewById(R.id.loader_msg);
if(T && !loaderStarted){
loader.start();
LAY.setVisibility(View.VISIBLE);
MTV.setText(msg);
loaderStarted = true;
}
else if(T && loaderSuspended && loaderStarted){
loader.resume();
LAY.setVisibility(View.VISIBLE);
MTV.setText(msg);
loaderSuspended = false;
}
else if (loaderStarted && !loaderSuspended) {
loader.suspend();
LAY.setVisibility(View.GONE);
loaderStarted = false;
loaderSuspended = true;
}
}
那么我需要这样一种方法:
//first make loading icon visible then call :
final private Thread loader = new Thread(new Runnable(){
@Override
public void run() {
int i = 0;
while (true){
if(loader.isInterrupted()){
return;
}
try {Thread.sleep(25);} catch (InterruptedException e) {}
final int j = i;
runOnUiThread(new Runnable(){
public void run() {
ImageView imageView = (ImageView) findViewById(R.id.loaderImage);
Matrix matrix = new Matrix();
imageView.setScaleType(ScaleType.MATRIX);
int newWIDTH = imageView.getWidth();
int newHIEGHT = imageView.getHeight();
matrix.postScale(((float)(newWIDTH))/imageView.getDrawable().getBounds().width(), ((float)(newHIEGHT))/imageView.getDrawable().getBounds().height());
matrix.postRotate((float) j, newWIDTH/2, newHIEGHT/2);
imageView.setImageMatrix(matrix);
}
});
i = (i + 15) % 360;
}
}
});
void setLoader(boolean T, String msg){
View LAY = findViewById(R.id.loaderLayout);
TextView MTV = (TextView) findViewById(R.id.loader_msg);
if(T && !loaderStarted){
loader.start();
LAY.setVisibility(View.VISIBLE);
MTV.setText(msg);
loaderStarted = true;
}
else if(T && loaderSuspended && loaderStarted){
loader.resume();
LAY.setVisibility(View.VISIBLE);
MTV.setText(msg);
loaderSuspended = false;
}
else if (loaderStarted && !loaderSuspended) {
loader.suspend();
LAY.setVisibility(View.GONE);
loaderStarted = false;
loaderSuspended = true;
}
}
暂停线程,然后恢复它
(.suspend()和.resume()已弃用)
提前感谢:)
对于糟糕的英语(:D)很抱歉,最好在
线程中引入布尔标志实现:
final private volatile boolean isSuspended = false;
然后您可以将此标志设置为true
/false
,并在run
方法中重写挂起逻辑,如下所示:
while (true) {
while (isSuspended) {
try {Thread.sleep(25);} catch (InterruptedException e) {}
}
...
}
您可以尝试添加字段:
// defines the paused state
private volatile boolean isPaused = false;
// a monitor object for wait/notify pattern
private final Object suspender = new Object();
那么在你的逻辑中:
void pause(){
synchronized(suspender){
isPaused = true;
}
}
void resume(){
synchronized(suspender){
isPaused = false;
suspender.notify();
}
}
while (true){
if(loader.isInterrupted()){
return;
}
// this outside loop is needed to deal with spurious wakeup
synchronized (suspender){
while(isPaused){
suspender.wait();
}
}
...
}
关于等待和通知的更多信息:答案建议使用不同的实现的原因是java线程不能直接调用另一个线程上的sleep。这样,你知道,让自己睡觉的线程不是在做一些危险的事情。(在同步过程中保持锁定等)您有可怕的变量命名标准。。。你应该考虑遵循这些标准,这样你的代码就更可读了。MIN SDK是:8可以吗?我的意思是设备的cpu不足,没有升级到2.3.6,那么这段代码不会降低程序的运行速度吗?如果您恢复并通知suspender,然后上下文切换到您的工作线程(isPaused
仍然是true
),你们进入循环,再等一次——恢复失败——我必须承认我还并没有测试它,我已经修复了我认为可能是错误的东西。你试过运行这个程序吗,或者你认为它在概念上是错误的?我认为改变顺序也没有帮助。在这两种情况下,锁定作业线程的机会都很小。有了新代码,如果你一个接一个地快速调用pause()
/resume()
,你也可以陷入wait()
调用。好的,我明白了。我已经为原子状态转换添加了synchronized
块,它们应该可以解决这个问题。谢谢你的指点!