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.html

    oder da:
    https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

    und 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.


Anmelden zum Antworten