编辑:我发现我在下面描述的内容只出现在我的模拟设备上(Nexus 5,目标api 19,4.4.2带有Intel Atom(x86)cpu),但不在我的物理设备上(HTC)一)....
EDIT2:Edit1是由于我没有抓到的IllegalStateException。在尝试启动之前添加了一些代码来检查线程是否已经运行。结合已接受的答案解决了我的问题。
我已经实现了一个在activity的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();
}
但我的线程没有恢复。有什么想法吗?感谢任何帮助。
马库斯
答案 0 :(得分:2)
我认为所有答案都有关于运行变量的一些问题,因为无法在没有Threads
<的情况下从两个不同的synchronized block
写入和读取变量/ strong>所以我发表自己的答案:
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
才能访问它们。
如果您有任何问题,请询问。
答案 1 :(得分:1)
语句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
答案 2 :(得分:0)
这是因为Runnable
循环在while
循环停止时停止。你可以试试这个:
Runnable work = new Runnable() {
@Override
public void run() {
while () {
if(running){
//Doing work
}
}
}
};