Un po 'di storia sulla concorrenza
Passando valori nella concorrenza è la parte facile. Esaminare il tipo di dati AtomicInteger
(Ulteriori informazioni here). Atomicità significa anche All or nothing
. Questo tipo di dati non sta necessariamente inviando dati tra thread o processori (come con lo mpi
) ma sta semplicemente condividendo i dati sulla sua memoria condivisa.
Ma ciò che è un'azione atomica? ....
Un'operazione atomica è un'operazione che viene eseguita come una singola unità di lavoro, senza la possibilità di interferenze da altre operazioni.
In Java la specifica del linguaggio garantisce che la lettura o la scrittura di una variabile sia atomica (a meno che la variabile non sia di tipo long o double). Lunga e doppio sono solo atomica se dichiarate come volatili ....
credito (Java Concurrency/Multithreading - Tutorial da Lars Vogel)
consiglio vivamente di leggere questo, che copre tutto, dai atomicity
, thread pools
, deadlocks
e the "volatile" and "synchronized" keyword
.
Inizio ClasseQuesto eseguirà un nuovo thread (Può anche essere indicato come il nostro 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
Poiché il numero intero è atomico, è anche possibile recuperare ovunque, ma il main method
nel Inizia Classe con System.out.println("[run start] current state is... "+state.intValue());
. (Se si desidera recuperare dalla main method
, si dovrà impostare un Setter/Getter, come ho fatto in Class Action)
Class ActionQuesta è la nostra discussione in azione (Può anche essere indicato come il nostro 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
output La console
[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
Come si può vedere, la AtomicInteger state
è condiviso nella memoria tra le nostre discussioni r
e p
.
Solution e Cose da cercare ...
L'unica cosa che dovete guardare quando si fa la concorrenza è Race Conditions
/Deadlocks
/Livelocks
. Alcuni RaceConditions
si verificano perché Threads
vengono creati in ordine casuale (e la maggior parte dei programmatori pensa nella sequenza mentale di ordine sequenziale).
ho la linea Thread.sleep(1000);
modo che il mio Main Thread
dà il filo schiavo r
un po 'di tempo per aggiornare il state
(prima di consentire p
per eseguire), causa del ordine casuale di fili.
1) Mantenere un riferimento al thread e passare il valore con un metodo. credito (SJuan76, 2012)
Nella soluzione che ho postato io faccio il mio Main Thread
(aka class start
) come il mio comunicatore principale per tenere traccia del Atomic Integer
per i miei schiavi da utilizzare (aka class action
). Il thread principale è anche updating
il memory buffer
per il Atomic Integer
per i miei slave (L'aggiornamento sul buffer di memoria si verifica sullo sfondo dell'applicazione ed è gestito dalla classe AtomicInteger
).
Ho aggiornato la mia risposta con 2 classi e un'implementazione funzionante di "AtomicInteger". Saluti – Killrawr