Threads
-
Hallo,
man soll 2 Threads machen. Der 1.Thread gibt gerade Zahlen aus, der 2.Thread die ungeraden. Das ganze bis zur Zahl 19.
Was haltet ihr von meiner Implementierung. Wo gibt es Verbesserungspotential?//class SharedObject public class SharedObject { static volatile public int counter = 0; } //class ThreadEvenNumber public class ThreadEvenNumber implements Runnable { @Override public void run() { while(SharedObject.counter <20) { if((SharedObject.counter %2 == 0) && (SharedObject.counter <20)) { System.out.println(SharedObject.counter); SharedObject.counter++; } } } } //class ThreadOddNumber public class ThreadOddNumber implements Runnable { @Override public void run() { while(SharedObject.counter <20) { if((SharedObject.counter %2 == 1) && (SharedObject.counter <20)) { System.out.println(SharedObject.counter); SharedObject.counter++; } } } } //class Main public class Main { public static void main(String[] args) { Thread t1 = new Thread( new ThreadEvenNumber() ); t1.start(); Thread t2 = new Thread( new ThreadOddNumber() ); t2.start(); } }
-
Würdest du den Zugriff auf den Counter ordentlich synchronisieren, bräuchtest du nicht doppelt auf < 20 prüfen und die Threads würden sich abwechselnd schlafen legen statt unnötig CPU-Zeit in der Schleife zu verbraten.
-
wie bekomm ich das denn hin, dass der Zugriff auf die Variable nur von einem Thread moeglich ist ?? So gehts nicht ..
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class SharedObject { static volatile public int counter = 0; static final Lock lock = new ReentrantLock(); static int accessCounter() { lock.lock(); return counter; lock.unlock(); } }
-
so gehts zumindest. Sieht aber wohl etwas umstaendlich aus..
//class SharedObject import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class SharedObject { static volatile public int counter = 0; static final Lock lock = new ReentrantLock(); static int accessCounter() { lock.lock(); return counter; } static void releaseCounter() { lock.unlock(); } } //class ThreadEvenNumber public class ThreadEvenNumber implements Runnable { @Override public void run() { while(SharedObject.accessCounter() <20) { if(SharedObject.counter %2 == 0) { System.out.println(SharedObject.counter); SharedObject.counter++; } SharedObject.releaseCounter(); } } }
-
schau mal da:
https://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.htmloder da:
https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.htmlund in deiner MainMethode brauchts musst Du auf das Ende der Threads warten.
//class Main public class Main { public static void main(String[] args) { Thread t1 = new Thread( new ThreadEvenNumber() ); t1.start(); Thread t2 = new Thread( new ThreadOddNumber() ); t2.start(); t1.join(); t2.join(); } }
Du musst garantieren, dass die Sperre wieder freigegeben wird.
public class SharedObject { static volatile public int counter = 0; static final Lock lock = new ReentrantLock(); static int accessCounter() { try { lock.lock(); return counter; } finally { lock.unlock(); } } }
wobei das freilich Quatsch ist, da lesende Zugriffe von Haus aus ThreadSafe sind. Aber so könnte das schon was werden:
public class SharedObject { static volatile public int counter = 0; static final Lock lock = new ReentrantLock(); static void accessCounterIncrement() { try { lock.lock(); counter++; } finally { lock.unlock(); } } }
in .Net oder Win32-Api gibt's dafür die Interlocked-Funktionen wie
Interlocked.Increment
https://msdn.microsoft.com/de-de/library/dd78zt0c(v=vs.110).aspx
Eventuell kannst Du Dir aus diesen Funktionen einen Satz an equivalenten Funktionen für Java erstellen. So zur Übung und zum Verständnis.
Wenn Du nicht komplett auf Java fixiert bist solltest auf jeden Fall hier
http://www.albahari.com/threading/
interessante Informationen finden. Die Multithread-Problematik ist von der
Sprache unabhängig.