Android Concurrency

From GT RoboJackets

Jump to: navigation, search

TODO:
cleanup
aliases for Techniques
add AsyncTask

Contents

Overview

Scheduling

make sure important things have enough time to execute
Runnable which execute continuously vs ones which need to be executed repeatedly
timeouts

  • behavior for handling
  • maybe leave this up to the Runnable

ScheduledThreadPoolExecutor

makes the Runnable start (doesn't control exact execution times, that is handled by the hardware) after every period. If the thread is still running, it waits until it finishes and then immediately starts it.

Communication

There are numerous ways to communicate between concurrently running code in Android. You can use all of the standard Java functionality along with several Android-specific methods. Unfortunately much of the documentation for Android can be very confusing, and it is hard to know when and where each approach is appropriate to use. This section attempts to explain the differences in each method of communication.

Summary

table

Intra-Process vs Inter-Process

Data that: needs to be acted upon immediately: Intents doesn't change often and can wait around: Messages changes often and only the latest value matters: Shared? changes often and all (new?) values matters: Shared Buffer?

best way to used shared variables • want it to be part of the class


Maybe our solution is we should use a mixture of these methods:

For data that is being used by many different threads or is updated and read frequently (like the current position), I would suggest that we either use Intents(2) or a custom data type that doesn't have to be synchronized, maybe using atomic writes. Now that I think about it, Atomic writes are probably the best idea.

For data that needs to be acted on sequentially or buffered (takes a long time to process), we should use Messages(3). Using messages for things that change really fast (ex. current position) would be a bad idea because we would end up overflowing our queue and maybe losing some important messages -- and like I said, there can only be one Message queue per thread.

Personally, I would rather use native Java functionality over Android stuff, mainly because I think the Android stuff is really hard to understand. However, I would probably rather use Android features than have to import other people's libraries(4) into our project.


Other Notes: - maybe use shared variables when multiple people need old (buffered) values -- (e.g. position data) - - might also want to send intents for people who want updates (don't want to poll) - if use Intents, we can supply our own buffers - - that way we can also have more control over scheduling - need to test Intent efficiency - is there a way to pull multiple messages off of message queue - - if not, we may end up having to use our own buffers anyway to prevent overflow and allow the filters to act on multiple pieces of new data at once.

Java Shared Variables

Massive synchronization

Data:

We can make everything that needs to be shared a shared variable.

Read/Writing:

Shared variables must be either synchronized or use atomic reads and writes. Variables can be synchronized by the code which is reading/writing to the variable (using the "synchronized" keyword) or directly through the variable's class.


Synchronization has a few pitfalls. In our case, since we have classes which are circularly accessing each other's data (controls-positioning), I would be most worried about deadlocks. Also, most of our shared variables will be changing very fast, so there might be a lot of overhead if each thread has to wait every time they access it.

atomic writes

That being said, I think that synchronization would be okay for most of the things we have to communicate between threads, especially for things that aren't being updated all that fast (waypoint position, for example).

Pros:

  • easy to understand

Cons:

  • requires a lot of extra planning and care
  • if we aren't careful, it will be inefficient or randomly die

Android Intents

Data:

Intents contain an name (string) and extras, each of which has a name (string) and data (floats, ints, Bundle, etc.).

Sending:

Intents can be broadcasted either to everyone who is listening or to a specific class. When sent directly to a class, the receiver can send a return value. When broadcasted, they can be sent normally (asynchronous, most efficient, no return values) or ordered (each receiver called in order, each receiver can propagate data to the next receiver or back to the sender).

Receiving:

Intents can be received by registering a callback or by implementing the callbacks built into Activity or Service.

Pros:

  • very efficient (as far as I can tell)
  • several different ways to send messages

Cons:

  • may mess up our attempts at scheduling (threads get interrupted directly)
  • no built-in queue/buffering
  • somewhat difficult to understand

Android Message Passing

Data:

A Message has several ways to store data: a Bundle, an Object, and a couple of ints. It also has a place to store a reference to the sender (so the receiver can send a reply).

Sending: Messages are pushed onto the receiver's message queue asynchronously.

Receiving:

Received messages are pulled off (polled) of their message queue and processed.

Pros:

  • built-in queue
  • gives us complete control over scheduling (we can tell each thread exactly when to run)

Cons:

  • no built-in broadcasts (must know who you are sending messages to)
  • only one sender/receiver/queue per thread
  • slightly less efficient
  • somewhat difficult to understand

Outside libraries

We can also use any number of other Java libraries to do this.

Pros:

  • more choice

Cons:

  • more annoying to compile
  • have to learn how to use that library
Personal tools