Java 线程:启动、挂起、恢复

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)

我正在制作一个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);
    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
块,它们应该可以解决这个问题。谢谢你的指点!