编辑:我发现我在下面描述的内容只发生在我的模拟设备上(Nexus 5,目标 api 19,4.4.2 与英特尔凌动 (x86( cpu(,而不是在我的物理设备(HTC One(上。
编辑2:Edit1是由于我没有捕获的非法状态异常。添加了一些代码以在尝试启动线程之前检查线程是否已运行。这与接受的答案相结合解决了我的问题。
我已经实现了一个活动,它在活动的 onCreate 方法中启动一个新线程,如下所示:
...
private boolean running;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
running = true;
new Thread(null, work, "myThread").start();
}
Runnable work = new Runnable() {
@Override
public void run() {
while (running) {
//Doing work
}
}
};
我正在使用活动的 onPause 方法"暂停"我的线程,如下所示:
@Override
protected void onPause() {
running = false;
super.onPause();
}
所以我认为恢复它同样容易......
@Override
protected void onResume(){
running = true;
super.onResume();
}
但我的线程没有恢复。知道为什么吗?感谢任何帮助。
马库斯
所有答案都与您的运行变量有关,因为您无法在没有synchronized block
的情况下从两个不同的Threads
写入和读取变量,所以我发布了自己的答案:
package com.example.threadandtoast;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
public class MonitorObject{
public boolean running = true;
public String message = "";
public boolean mustBePost = true;
}
Thread t;
int threadNameCounter = 0; // i use this variable to make sure that old thread is deleted
// when i pause, you can see it and track it in DDMS
Runnable work = new Runnable() {
boolean myRunning;
@Override
public void run() {
synchronized(mSync) {
myRunning = mSync.running;
}
while (myRunning) {
runOnUiThread(new Runnable() { // in order to update the UI (create Toast)
@Override // we must switch to main thread
public void run() {
// i want to read the message so i must use synchronized block
synchronized(mSync) {
// i use this variable to post a message just for one time because i am in an infinite loop
// if i do not set a limit on the toast i create it infinite times
if(mSync.mustBePost){
Toast.makeText(MainActivity.this, mSync.message, Toast.LENGTH_SHORT).show();
// the message post so i must set it to false
mSync.mustBePost = false;
// if i am going to pause set mSync.running to false so at the end of infinite loop
//of thread he reads it and leaves the loop
if(mSync.message.equals("Main Activity is going to pause")){
mSync.running=false;
}
}
}
}
});
synchronized(mSync) {
myRunning = mSync.running;
}
}
}
};
final MonitorObject mSync = new MonitorObject();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onPause() {
super.onPause();
synchronized(mSync) {
// mSync.running = false; you can not set it here because
// it is possible for the thread to read it and exit the loop before he posts your message
mSync.mustBePost=true;
mSync.message = "Main Activity is going to pause";
}
}
@Override
protected void onResume(){
super.onResume();
threadNameCounter++;
synchronized(mSync) {
mSync.running = true;
mSync.mustBePost=true;
mSync.message = "Main Activity is going to resume";
}
t = new Thread(work,"My Name is " + String.valueOf(threadNameCounter));
t.start();
}
}
或者您可以使用以下代码:
public class MainActivity extends ActionBarActivity {
Thread t;
int threadNameCounter = 0; // i use this variable to make sure that old thread is deleted
// when i pause, you can see it in DDMS
String message = "";
boolean isPost = false;
Runnable work = new Runnable() {
@Override
public void run() {
while (true) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if(!isPost){
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
isPost = true;
if( message.equals("Main Activity is going to pause")){
t.interrupt();
}
}
}
});
if(Thread.currentThread().isInterrupted()){
break;
}
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onPause() {
super.onPause();
message = "Main Activity is going to pause";
isPost = false;
}
@Override
protected void onResume(){
super.onResume();
message = "Main Activity is going to resume";
isPost = false;
threadNameCounter++;
t = new Thread(work,"My Name is " + String.valueOf(threadNameCounter));
t.start();
}
}
您还可以使用信号量或等待通知方法。
我把public String message = "";
和public boolean mustBePost = true;
放到 mSync 对象中,但它是没有必要,因为只有main thread
可以访问它们。
如果您有任何问题,请询问。
running = false;
将停止执行Thread
,而不是暂停它。使用两个变量:一个用于停止当前Thread
,另一个用于暂停和恢复Thread
,如下所示:
boolean isThreadPause=false;
Runnable work = new Runnable() {
@Override
public void run() {
while (running) {
if (!isThreadPause) {
// Doing work
}
}
}
};
在活动的onPause
事件中,将isThreadPause
设置为 true
,在onResume
事件中,将 isThreadPause
设置为 false
。
这是因为当while
循环停止时,您的Runnable
对象将停止。你可以试试这个:
Runnable work = new Runnable() {
@Override
public void run() {
while () {
if(running){
//Doing work
}
}
}
};