如何向处理程序发送中断以中断 Thread.sleep()?
How do I send an interrupt to a handler to break a Thread.sleep()?
我在服务中有一个处理程序,我会阻塞该线程,直到用户选择停止该服务。为了减少 CPU 强度,我尝试使用 Thread.sleep() 并在 10 minutes
间隔后重复检查阻塞条件。这是我对 handlemessage
的实现:
@Override
public void handleMessage(Message msg) {
Log.e("Service", "looper started");
GPSThread gp=new GPSThread(getApplicationContext());
gp.start();
ModeController mc=new ModeController(getApplicationContext());
mc.start();
NetworkSniffer nh=new NetworkSniffer(getApplicationContext());
nh.start();
while(stopService) //stopService is a volatile boolean i use to block until user opts to stop the service
{
try {
Thread.sleep(10*60*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mc.stopThread();
gp.stopThread();
nh.stopNetworkThread();
stopSelf(msg.arg1);
}
现在我的问题是,如果我将 stopService 的值更改为 false(通过 public 函数),可能需要 10 分钟才能退出 while 循环。如果它是一个线程,我会使用 Thread.interrupt() 并退出 while 循环。
所以我的问题是如何为 Handler 实现类似的事情,即如何在 Handler 中为 Thread.sleep() 抛出 InterruptedException。
If it were a thread I would have used a Thread.interrupt() and quit the while loop.
实际上,代码 >><< 运行 在一个线程上,所以如果您能弄清楚那个线程是什么,就可以中断它。
撇开这一点,您应该这样做的方法是让代码位于您试图中断线程调用的位置 Service.stopService
。
参考文献:
- How to call stopservice() method of Service class from the calling activity class
- http://www.vogella.com/tutorials/AndroidServices/article.html#service_stop
当正在休眠的线程是服务的处理程序线程时,此方法有效。如果您自己明确创建了线程,那么您将需要跟踪我们创建的线程并在其上使用 Thread.interrupt
。 (并且您可以使用 Thread.interrupted
状态而不是自定义 stopService
标志。)
但是,更好的办法是避免 sleep
循环:
感谢@Stephen C 终于让它工作了。发布我的代码,希望它能在将来对其他人有所帮助:
package com.example.userpc.roadtracker;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.util.Log;
/**
* Created by USER PC on 5/21/2016.
*/
public class MainServiceThread extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private volatile static boolean stopService=true;
private static HandlerThread mThread;
public static void stopServiceThread()
{
stopService=false;
mThread.interrupt();
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
Log.e("Service", "looper started");
GPSThread gp=new GPSThread(getApplicationContext());
gp.start();
ModeController mc=new ModeController(getApplicationContext());
mc.start();
NetworkSniffer nh=new NetworkSniffer(getApplicationContext());
nh.start();
while(stopService)
{
try {
Thread.sleep(10*60*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mc.stopThread();
gp.stopThread();
nh.stopNetworkThread();
stopSelf(msg.arg1);
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
Log.e("Service", "in onCreate");
stopService=true;
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
mThread=thread;
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("Service","Started");
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
mThread=null;
Log.e("Service","Destroyed");
}
}
我在服务中有一个处理程序,我会阻塞该线程,直到用户选择停止该服务。为了减少 CPU 强度,我尝试使用 Thread.sleep() 并在 10 minutes
间隔后重复检查阻塞条件。这是我对 handlemessage
的实现:
@Override
public void handleMessage(Message msg) {
Log.e("Service", "looper started");
GPSThread gp=new GPSThread(getApplicationContext());
gp.start();
ModeController mc=new ModeController(getApplicationContext());
mc.start();
NetworkSniffer nh=new NetworkSniffer(getApplicationContext());
nh.start();
while(stopService) //stopService is a volatile boolean i use to block until user opts to stop the service
{
try {
Thread.sleep(10*60*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mc.stopThread();
gp.stopThread();
nh.stopNetworkThread();
stopSelf(msg.arg1);
}
现在我的问题是,如果我将 stopService 的值更改为 false(通过 public 函数),可能需要 10 分钟才能退出 while 循环。如果它是一个线程,我会使用 Thread.interrupt() 并退出 while 循环。
所以我的问题是如何为 Handler 实现类似的事情,即如何在 Handler 中为 Thread.sleep() 抛出 InterruptedException。
If it were a thread I would have used a Thread.interrupt() and quit the while loop.
实际上,代码 >><< 运行 在一个线程上,所以如果您能弄清楚那个线程是什么,就可以中断它。
撇开这一点,您应该这样做的方法是让代码位于您试图中断线程调用的位置 Service.stopService
。
参考文献:
- How to call stopservice() method of Service class from the calling activity class
- http://www.vogella.com/tutorials/AndroidServices/article.html#service_stop
当正在休眠的线程是服务的处理程序线程时,此方法有效。如果您自己明确创建了线程,那么您将需要跟踪我们创建的线程并在其上使用 Thread.interrupt
。 (并且您可以使用 Thread.interrupted
状态而不是自定义 stopService
标志。)
但是,更好的办法是避免 sleep
循环:
感谢@Stephen C 终于让它工作了。发布我的代码,希望它能在将来对其他人有所帮助:
package com.example.userpc.roadtracker;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.util.Log;
/**
* Created by USER PC on 5/21/2016.
*/
public class MainServiceThread extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private volatile static boolean stopService=true;
private static HandlerThread mThread;
public static void stopServiceThread()
{
stopService=false;
mThread.interrupt();
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
Log.e("Service", "looper started");
GPSThread gp=new GPSThread(getApplicationContext());
gp.start();
ModeController mc=new ModeController(getApplicationContext());
mc.start();
NetworkSniffer nh=new NetworkSniffer(getApplicationContext());
nh.start();
while(stopService)
{
try {
Thread.sleep(10*60*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mc.stopThread();
gp.stopThread();
nh.stopNetworkThread();
stopSelf(msg.arg1);
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
Log.e("Service", "in onCreate");
stopService=true;
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
mThread=thread;
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("Service","Started");
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
mThread=null;
Log.e("Service","Destroyed");
}
}