Un poco de historia sobre la concurrencia
Pasar valores en concurrencia es la parte fácil. Mire en el tipo de datos AtomicInteger
(Más información here). Atomicity también significa All or nothing
. Este tipo de datos no necesariamente está enviando datos entre subprocesos o procesadores (como lo haría con mpi
), sino que simplemente está compartiendo datos en su memoria compartida.
Pero lo que es una acción atómica? ....
una operación atómica es una operación que se lleva a cabo como una sola unidad de trabajo sin posibilidad de interferencia de otras operaciones.
En Java, la especificación del lenguaje garantiza que leer o escribir una variable es atómico (a menos que la variable sea de tipo largo o doble). De largo y dobles sólo atómica si se declaran como volátil ....
crédito (Java Concurrency/Multithreading - Tutorial por Lars Vogel)
le recomiendo que lea esto, que cubre todo, desde atomicity
, thread pools
, deadlocks
y the "volatile" and "synchronized" keyword
.
Iniciar claseEsto ejecutará un nuevo hilo (También puede ser referido como nuestra 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
Debido a que el número entero es atómico, también se puede recuperar en cualquier lugar, pero el main method
en el Iniciar clase con System.out.println("[run start] current state is... "+state.intValue());
. (Si desea recuperarlo de la main method
, tendrá que configurar un Setter/Getter, como lo he hecho en el Acción Clase)
Acción ClaseEste es nuestro hilo en la acción (También se lo puede llamar nuestro 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
de salida La consola
[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
Como se puede ver, el AtomicInteger state
está siendo compartida en la memoria entre nuestros hilos r
y p
.
solución y cosas que buscan ...
Lo único que hay que tener cuidado al hacer la concurrencia es Race Conditions
/Deadlocks
/Livelocks
. Algunos RaceConditions
se producen porque Threads
se crean en orden aleatorio (y la mayoría de los programadores piensan en el conjunto mental de orden secuencial).
que tienen la línea Thread.sleep(1000);
para que mi Main Thread
da el flujo esclavo r
un poco de tiempo para actualizar el state
(antes de permitir p
para correr), debido a la orden aleatorio de hilos.
1) Mantenga una referencia al hilo y pase el valor con un método. crédito (SJuan76, 2012)
En la solución que he publicado yo hago mi Main Thread
(también conocido como class start
) como mi comunicador principal para realizar un seguimiento de la Atomic Integer
para mis esclavos a utilizar (también conocido como class action
). Mi hilo principal también es updating
memory buffer
para Atomic Integer
en mis esclavos (La actualización en el búfer de memoria ocurre en el fondo de la aplicación y es manejada por la clase AtomicInteger
).
He actualizado mi respuesta con 2 clases y una implementación en funcionamiento del 'AtomicInteger'. Saludos – Killrawr