Passing a value from activity to thread after thread is already created

android, android-activity, java, multithreading

Solution

A little background on concurrency

Passing values in concurrency is the easy part. Look into the `AtomicInteger` data type (More information here). Atomicity also means `All or nothing`. This data type isn't necessarily sending data between threads or processors (like you would with `mpi`) but it is merely sharing data on its shared memory.

But what is an Atomic Action?....

An atomic operation is an operation which is performed as a single unit of work without the possibility of interference from other operations.

In Java the language specification guarantees that reading or writing a variable is atomic (unless the variable is of type long or double). Long and double are only atomic if they declared as volatile....

Credit(Java Concurrency / Multithreading - Tutorial by Lars Vogel)

I highly recommend you read this, it covers everything from `atomicity`, `thread pools`, `deadlocks` and `the "volatile" and "synchronized" keyword`.

Start Class This will execute a new thread (It can also be referred to as our `Main Thread`).

import java.util.concurrent.atomic.AtomicInteger;
/**
 * @author Michael Jones
 * @description Main Thread
 */
public class start {
    private AtomicInteger state;
    private Thread p;
    private Thread r;
    /**
     * constructor
     * initialize the declared threads
     */
    public start(){
        //initialize the state
        this.state = new AtomicInteger(0);
        //initialize the threads r and p
        this.r = new Thread(new action("resume", state));
        this.p = new Thread(new action("pause", state));
    } //close constructor

    /**
     * Start the threads
     * @throws InterruptedException 
     */
    public void startThreads() throws InterruptedException{
        if(!this.r.isAlive()){
            r.start(); //start r
        }
        if(!this.p.isAlive()){
            Thread.sleep(1000); //wait a little (wait for r to update)...
            p.start(); //start p
        }
    } //close startThreads

    /**
     * This method starts the main thread
     * @param args
     */
    public static void main(String[] args) {
         //call the constructor of this class
        start s = new start();
        //try the code
        try {
            s.startThreads();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } //start the threads
    } //close main

} //close class start

Because the integer is atomic, you can also retrieve it anywhere but the `main method` in the Start Class with `System.out.println("[run start] current state is... "+state.intValue());`. (If you wish to retrieve it from the `main method`, you will have to setup a Setter/Getter, like I've done so in the Action Class)

Action Class This is our thread in action (It can also be referred to as our `Slave Thread`).

import java.lang.Thread.State;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Michael Jones
 * @description Slave Thread
 */
public class action implements Runnable {

    private String event = "";
    private AtomicInteger state;

    /**
     * The constructor (this represents the current instance of a thread).
     * 
     * @param event
     * @param state
     */
    public action(String event, AtomicInteger state) {
        this.event = event; // update this instance of event
        this.state = state; // update this instance of state
    } // constructor

    /**
     * This method will be called after YourThreadName.Start();
     */
    @Override
    public void run() {
        if (this.event == "resume") {
            this.OnResume(); // call resume
        } else {
            this.OnPause(); // call pause
        }
    } // close Runnable run() method

    /**
     * The resume function Use the auto lock from synchronized
     */
    public synchronized void OnResume() {
        System.out.println("[OnResume] The state was.." + this.getAtomicState()
                + " // Thread: " + Thread.currentThread().getId());
        this.setAtomicState(2); // change the state
        System.out.println("[OnResume] The state is.." + this.getAtomicState()
                + " // Thread: " + Thread.currentThread().getId());
    } // close function

    /**
     * The pause function Use the auto lock from synchronized
     */
    public synchronized void OnPause() {
        System.out.println("[OnPause] The state was.." + this.getAtomicState()
                + " // Thread: " + Thread.currentThread().getId());
        this.setAtomicState(1); // change the state
        System.out.println("[OnPause] The state is.." + this.getAtomicState()
                + " // Thread: " + Thread.currentThread().getId());
    } // close function

    /**
     * Get the atomic integer from memory
     * 
     * @return Integer
     */
    private Integer getAtomicState() {
        return state.intValue();
    }// close function

    /**
     * Update or Create a new atomic integer
     * 
     * @param value
     */
    private void setAtomicState(Integer value) {
        if (this.state == null) {
            state = new AtomicInteger(value);
        } else
            state.set(value);
    } // close function

} // close the class

The Console Output

[OnResume] The state was..0 // Thread: 9
[OnResume] The state is..2 // Thread: 9
[OnPause] The state was..2 // Thread: 10
[OnPause] The state is..1 // Thread: 10

As you can see, the `AtomicInteger state` is being shared in the memory between our threads `r` and `p`.

Solution and Things to look for...

The only thing you have to watch when doing concurrency is `Race Conditions`/`Deadlocks`/`Livelocks`. Some `RaceConditions` occur because `Threads` are created in random order (And most programmers think in the mind set of sequential order).

I have the line `Thread.sleep(1000);` so that my `Main Thread` gives the slave thread `r` a little time to update the `state` (before allowing `p` to run), due to the random order of threads.

1) Keep a reference to the thread and pass the value with a method. Credit (SJuan76, 2012)

In the solution I've posted I make my `Main Thread` (aka `class start`) as my main communicator to keep track of the `Atomic Integer` for my slaves to use (aka `class action`). My main thread is also `updating` the `memory buffer` for the `Atomic Integer` on my slaves (The update on the memory buffer occurs in the background of the application and is handled by the `AtomicInteger` class).

Problem

In my android program an Activity calls a new surface view class, which then in turn calls a new thread class. I want to be able to pass a value to the thread class from the activity's onPause and onResume methods, so I can pause and resume the thread. The only way I know to pass this data is by creating a new instance, which would just create a different thread. How should I go about this without creating a new thread instance? ``` public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new GameSurface(this)); } @Override protected void onResume() { super.onResume(); //Would like to pass this value int state = 1; } @Override protected void onPause() { super.onPause(); //Would like to pass this value int state = 2; } ```

Original source