背景
我的应用程序创建了许多后台线程来并行化复杂的迭代任务。在每次迭代结束时,我需要所有后台线程共享数据,同步并再次迭代。我通过创建一组HandlerThread
然后将我的迭代作为Runnable
传递来实现这一点。消息传递在每次迭代内部 run()
(问题的一部分)结束时执行。
问题
Android developer documentation提供了有关如何将处理程序附加到UI线程以处理来自后台任务的传入消息的指导。因为UI线程应该没有负载来响应触摸事件等,所以只要消息到达队列就会调用handleMessage()
,因为它没有做任何其他事情。在我的问题中,后台线程仍在处理我的Runnable
(即它正在运行run()
代码),因此,虽然消息被发布到队列,但它们不会被接收线程处理因为他们忙于做run()
。
问题
来自在C ++中使用MPI,我的消息发送和接收概念感觉应该有一种方法来阻塞线程,直到它从队列中抓取并处理消息。 wait()
将暂停整个线程,这将无济于事。
之前我曾使用AsyncTask
进行此类工作,但发现这些任务与static AtomicIntegers
混乱并最终有很多静态变量,以确保每个任务都可以在不使用处理程序的情况下访问
AsyncTask
?型号代码
MainActivity.java是:
public class MainActivity extends AppCompatActivity {
public static boolean run_flag = false;
public static final int numThreads = 2;
static Vector<Handler> handlerArray = new Vector<>(numThreads);
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.mybutton);
// Create barrier and start each thread
run_flag = true;
CyclicBarrier barrier = new CyclicBarrier(numThreads);
for (int i = 0; i < numThreads; i++) {
HandlerThread t = new HandlerThread("Thread" + i);
t.start();
// Create handler, attach to the new thread, store reference in static array
handlerArray.addElement( new Handler(t.getLooper()) {
// Define handler for message processing
@Override
public void handleMessage(Message incoming_msg) {
// Do something with the passed value
Log.d("Handler " + android.os.Process.myTid(), "Handling message");
}
} );
// Pass runnable to this new thread
handlerArray.get(i).post( new MyRunnable(i, barrier) );
}
// Attach listener to button
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Stop the runnables
run_flag = false;
}
});
}
}
MyRunnable.java是:
public class MyRunnable implements Runnable {
// Fields
int value;
CyclicBarrier barrier;
int id;
// Constructor
public MyRunnable(int id, CyclicBarrier barrier) {
this.value = 0;
this.barrier = barrier;
this.id = id;
}
// Inner container class
class MyContainer {
int messagevalue;
public MyContainer(int msg_value) {
this.messagevalue = msg_value;
}
}
@Override
public void run( ) {
Log.d("Runnable " + android.os.Process.myTid(), "Starting Runnable");
while (MainActivity.run_flag) {
// Do something //
value++;
// Create and send a message to other thread
int destination = (id + 1 % MainActivity.numThreads) - 1;
Message msg =
MainActivity.handlerArray.get(destination).obtainMessage();
msg.obj = new MyContainer(10*value);
MainActivity.handlerArray.get(destination).sendMessage(msg);
// Synchronise before begin next iteration
try {
barrier.await();
} catch (Exception e) {
// Broken or interrupted exceptions handled here
e.printStackTrace();
}
}
Log.d("Runnable " + android.os.Process.myTid(), "Stopping Runnable, Value = " + value);
}
}