Java 线程在几次迭代后被终止
我试图创建一个包含服务的应用程序,该服务在设备启动时启动,然后记录一些事件 manifest.xml中的服务条目Java 线程在几次迭代后被终止,java,android,multithreading,Java,Android,Multithreading,我试图创建一个包含服务的应用程序,该服务在设备启动时启动,然后记录一些事件 manifest.xml中的服务条目 <receiver android:name="com.myservices.BReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <category android:na
<receiver android:name="com.myservices.BReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<service android:name="com.myservices.MyService" >
</service>
MService.class
public class MyService extends IntentService {
private static final String TAG = "MyService";
private static final long TIMER = 2000;
public MyService() {
super("MyService");
}
@Override
protected void onHandleIntent(Intent intent) {
startLogginThread();
}
/**
* For logging
*/
private void startLogginThread() {
Thread thread = new Thread() {
public void run() {
while (true) {
try {
// Logging events
myLogger();
Log.e(TAG, "Awake");
// TIMER
Thread.sleep(TIMER);
} catch (Exception e) {
Log.e("MyService", "local Thread error "+ e.toString());
}
}
}
};
thread.start();
}
private void myLogger() {
// Creating new file to store logs.
// Check if SD card is available else use internal memory.
File dir = null;
if (MyServiceUtil.isExternalStorageReadable() && MyServiceUtil.isExternalStorageWritable()) {
// External Memory
File sdCard = Environment.getExternalStorageDirectory();
dir = new File(sdCard.getAbsolutePath() + "/MyLogger");
dir.mkdirs();
} else {
// Internal Memory
dir = getFilesDir();
}
// Rename to txt for reading
File file = new File(dir, "log.txt");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
Log.e(TAG, "Exception :" + e.toString());
}
}
// Printing timestamp in file
try {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file, true)));
String timeStamp = new SimpleDateFormat("dd.MM.yyyy '-' HH:mm:ss").format(Calendar.getInstance().getTime());
out.println(timeStamp);
// Log Location
out.close();
Log.e("Logggging", timeStamp);
} catch (IOException e) {
Log.e(TAG, "Exception :" + e.toString());
}
}
@Override
public void onDestroy() {
Log.e(TAG, "onDestroy called");
super.onDestroy();
}
}
结果:
只有几次,比如6-7次日志被打印并存储在文件中。
以下是日志:
11-16 17:00:02.438: E/BReceiver(3187): onReceive started
11-16 17:00:02.438: E/BReceiver(3187): onReceive ended
11-16 17:00:02.458: E/MyService(3187): onDestroy called
11-16 17:00:02.458: D/MyServiceUtil(3187): isExternalStorageReadable started
11-16 17:00:02.468: D/MyServiceUtil(3187): isExternalStorageWritable started
11-16 17:00:02.468: E/Logggging(3187): 16.11.2014 - 17:00:02
11-16 17:00:02.468: E/MyService(3187): Awake
11-16 17:00:04.468: D/MyServiceUtil(3187): isExternalStorageReadable started
11-16 17:00:04.468: D/MyServiceUtil(3187): isExternalStorageWritable started
11-16 17:00:04.478: E/Logggging(3187): 16.11.2014 - 17:00:04
11-16 17:00:04.478: E/MyService(3187): Awake
11-16 17:00:06.478: D/MyServiceUtil(3187): isExternalStorageReadable started
11-16 17:00:06.488: D/MyServiceUtil(3187): isExternalStorageWritable started
11-16 17:00:06.488: E/Logggging(3187): 16.11.2014 - 17:00:06
11-16 17:00:06.488: E/MyService(3187): Awake
11-16 17:00:08.488: D/MyServiceUtil(3187): isExternalStorageReadable started
11-16 17:00:08.488: D/MyServiceUtil(3187): isExternalStorageWritable started
11-16 17:00:08.488: E/Logggging(3187): 16.11.2014 - 17:00:08
11-16 17:00:08.488: E/MyService(3187): Awake
另外,我不明白如果线程已经在运行,为什么会调用onDestroy:
11-16 17:00:02.458:E/MyService(3187):onDestroy呼叫
PS-这只发生在Kitkat中。要在BroadcastReceiver中执行后台任务,您需要调用sdk 11+,并在完成时调用Pendingreult.finish() 这可以由onReceive(上下文、意图)中的应用程序调用,以 允许它在从该位置返回后保持广播活动 功能。这并没有改变相对稳定的预期 响应广播(在10秒内完成),但允许 将与之相关的工作转移到另一个线程的实现 避免由于磁盘IO导致主UI线程出现故障 您可以在接收器中移动代码并使用goAsync,也可以直接在IntentService中运行代码,因为它与服务不同,它有自己的后台线程 更新
final PendingResult pendingResult = goAsync();
new Thread() {
public void run() {
while (SOME_CONDITION) {
try {
// Logging events
myLogger();
Log.e(TAG, "Awake");
// TIMER
Thread.sleep(TIMER);
} catch (Exception e) {
Log.e("MyService", "local Thread error "+ e.toString());
}
}
// Finish the broadcast.
pendingResult.finish();
}
}.start();
你对意向服务不太了解。onHandleIntent的方法是在框架启动的子线程中调用的,当onHandleIntent完成时,该服务将自行终止,因此原因是您将作业放在启动的新线程中。因此,您应该将代码放入OnHandleContent中
while (true) {
try {
// Logging events
myLogger();
Log.e(TAG, "Awake");
// TIMER
Thread.sleep(TIMER);
} catch (Exception e) {
Log.e("MyService", "local Thread error "+ e.toString());
}
}
如果您能尝试捕获Throwable而不是Exception,您可能会遇到错误。如果这样做,只捕获一次错误,否则可能会进入无限循环。在Android JVM中是否有任何承诺,无论内存多么低或其他条件如何,运行线程的活动都不会被杀死?谢谢,但我不明白如何使用goAsync()的挂起意图。我应该在我的Breceiver中调用goAsync()吗?如有可能,请更新您的答案,例如
while (true) {
try {
// Logging events
myLogger();
Log.e(TAG, "Awake");
// TIMER
Thread.sleep(TIMER);
} catch (Exception e) {
Log.e("MyService", "local Thread error "+ e.toString());
}
}