Passing a value from activity to a stream after the stream has already been created

In my android program, Activity calls a new surface view class, which in turn calls a new thread class. I want to be able to pass a value to the thread class from the onPause and onResume actions, so I can pause and resume the thread. The only way I can transfer this data is to create a new instance that would just create another thread. How do I get around 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; } 
+6
source share
3 answers

Small background on concurrency

Passing values ​​to concurrency is the easy part. Take a look at the AtomicInteger data AtomicInteger (more info here ). Atomicity also means All or nothing . This type of data does not necessarily send data between threads or processors (e.g. with mpi ), but it just uses the data in its shared memory.

But what is atomic action? ....

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

In Java, a language specification ensures 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 are declared unstable ....

Credit ( Java concurrency / Multithreading - A tutorial from Lars Vogel)

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


Launch class This will lead to the creation of a new thread (it can also be called 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 

Since the integer is atomic, you can also extract it anywhere, but the main method to the Start class using System.out.println("[run start] current state is... "+state.intValue()); . (If you want to get it from the main method , you will need to configure Setter / Getter, as was done in the action class )

Action class This is our thread in action (it can also be called 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 

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, AtomicInteger state is shared in memory between our threads r and p .


The solution and all you need to look for ...

The only thing you need to observe when executing concurrency: Race Conditions / deadlocks / Livelocks . Some RaceConditions arise because Threads are created in random order (and most programmers think in a sequential order mind set).

I have a string Thread.sleep(1000); so my Main Thread gives slave thread r little time to update state (before p starts) due to the random order of threads.

1) Keep a link to the stream and pass the value using the method. Credit ( SJuan76 , 2012)

In the solution I posted, I make my Main Thread (aka class start ) as the main communicator for tracking Atomic Integer for my slaves (aka class action ). My main thread is also updating memory buffer for Atomic Integer on my subordinates (Updating the memory buffer occurs in the background of the application and is processed by the AtomicInteger class) .

+4
source

1) Keep a link to the stream and pass the value using the method.

2) When creating a stream, pass it an object shared with Activity. Put the values ​​that you want to pass into the object, regularly check the stream until the values ​​are found.

+3
source

I use a reference class, which I call it Share Class . It has a variable of type volatile .

volatile is used to indicate that the value of a variable will be changed by different threads.

 public class Share { public static volatile type M_shared; } 

to change this variable, you must lock it, and after changing the value, release the lock. You can read and write using Share.M_shared .

+1
source

Source: https://habr.com/ru/post/921049/


All Articles