Stampa dispari di numero pari mediante thread

Stampa dispari di numero pari utilizzando thread.Creare una class thread, due istanze del thread. Uno stamperà il numero dispari e l’altro stamperà il numero pari.

Ho fatto la seguente codifica. Ma arriva allo stato di blocco morto. Qualcuno può spiegare quale potrebbe essere la ragione di ciò?

public class NumberPrinter implements Runnable{ private String type; private static boolean oddTurn=true; public NumberPrinter(String type){ this.type=type; } public void run() { int i=type.equals("odd")?1:2; while(i<10){ if(type.equals("odd")) printOdd(i); if(type.equals("even")) printEven(i); i=i+2; } } private synchronized void printOdd(int i){ while(!oddTurn){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(type + i); oddTurn=false; notifyAll(); } private synchronized void printEven(int i){ while(oddTurn){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(type + i); oddTurn=true; notifyAll(); } public static void main(String[] s){ Thread odd=new Thread(new NumberPrinter("odd")); Thread even=new Thread(new NumberPrinter("even")); odd.start(); even.start(); } } 

Out Put: odd1 even2


poi arriva a deadlock !!!!!!

Grazie per l’aiuto.

Stai aspettando e notificando oggetti diversi ( monitor ).

L’idea è che puoi chiamare obj.wait() per aspettare che qualcuno faccia obj.notify() , mentre stai facendo objA.wait() e objB.notify() .

Cambia il tuo metodo printOdd in qualcosa di simile

 private void printOdd(int i) { synchronized (lock) { // < ------- while (!oddTurn) { try { lock.wait(); // <------- } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(type + i); oddTurn = false; lock.notifyAll(); // <------- } } 

e il metodo printEven allo stesso modo.

Quindi fornire il NumberPrinter con un object di lock :

 Object lock = new Object(); Thread odd = new Thread(new NumberPrinter("odd", lock)); Thread even = new Thread(new NumberPrinter("even", lock)); 

Produzione:

 odd1 even2 odd3 even4 odd5 even6 odd7 even8 odd9 

Ci sono molti bug nel codice.

Prima di tutto, le dichiarazioni synchronized non hanno alcun effetto. Si creano due istanze di thread e ciascuna chiama solo i propri metodi. synchronized è utile solo se un altro thread può chiamare un metodo.

Quindi notifyAll() non ha effetto per gli stessi motivi. odd.notifyAll() non raggiunge even sospeso nell’attesa wait() .

Quindi quello di cui hai bisogno è un altro object che contenga lo stato e che entrambi i thread possano vedere e utilizzare. Usa synchronized , wait() e notifyAll() su quella terza istanza.

Lo stesso può essere risolto utilizzando l’interfaccia di blocco:

NaturalOrder.java

 import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class NaturalOrder { public int currentNumber = 1; public boolean evenOdd = false; Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); public static void main(String[] args) { NaturalOrder naturalOrder = new NaturalOrder(); Thread t1 = new Thread(new OddNumberLock(naturalOrder, naturalOrder.lock, naturalOrder.condition)); Thread t2 = new Thread(new EvenNumberLock(naturalOrder, naturalOrder.lock, naturalOrder.condition)); t1.start(); t2.start(); } } 

OddNumberLock.java

 import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; public class OddNumberLock implements Runnable { NaturalOrder naturalOrder; Lock lock; Condition condition; public OddNumberLock(NaturalOrder naturalOrder, Lock lock, Condition condition) { this.naturalOrder = naturalOrder; this.lock = lock; this.condition = condition; } @Override public void run() { lock.lock(); while (naturalOrder.currentNumber < 20) { while (naturalOrder.evenOdd != false) { try { condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } try { Thread.sleep(ThreadLocalRandom.current().nextInt(1000)); } catch (InterruptedException e) { e.printStackTrace(); } if (naturalOrder.currentNumber % 2 != 0) { System.out.println(naturalOrder.currentNumber); } naturalOrder.currentNumber++; naturalOrder.evenOdd = true; condition.signalAll(); } lock.unlock(); } } 

EvenNumberLock.java

 import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; public class EvenNumberLock implements Runnable { NaturalOrder naturalOrder; Lock lock; Condition condition; public EvenNumberLock(NaturalOrder naturalOrder, Lock lock, Condition condition) { this.naturalOrder = naturalOrder; this.lock = lock; this.condition = condition; } @Override public void run() { lock.lock(); while (naturalOrder.currentNumber < 20) { while (naturalOrder.evenOdd != true) { try { condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } try { Thread.sleep(ThreadLocalRandom.current().nextInt(1000)); } catch (InterruptedException e) { e.printStackTrace(); } if (naturalOrder.currentNumber % 2 == 0) { System.out.println(naturalOrder.currentNumber); } naturalOrder.currentNumber++; naturalOrder.evenOdd = false; condition.signalAll(); } lock.unlock(); } } 

Penso che il problema potrebbe essere che printOdd e printEven sincronizzano su un blocco diverso (i blocchi dell’istanza dell’object Thread). Pertanto non hai garantito che la modifica della variabile statica oddTurn sarà visibile nell’altro thread. Cerca di rendere il volatile oddTurn all’inizio.

Ho fatto così

 public class OddEven{ public static void main(String[] args){ Print o=new Print(); Thread even=new Thread(new MyRunnable(2,o)); Thread odd=new Thread(new MyRunnable(1,o)); even.start(); odd.start(); } } class MyRunnable implements Runnable{ int start; Print ob; MyRunnable(int s,Print o){ start=s; ob=o; } public void run(){ for(int i=start;i< =20;i+=2) ob.display(i); } } class Print{ int rem=0; synchronized void display(int n){ while(n%2==rem) try{ wait(); } catch(Exception e){System.out.println("Display interrupted");} System.out.print(n+" "); rem=n%2; notify(); } } 

Ti manca la parola chiave volatile all’interno oddTurn variabile oddTurn . Senza di esso non ci sono garanzie che i thread vedano il valore reale.

Ho usato un object condiviso per controllare l’ordine di esecuzione

 class Counter implements Runnable { int count; static Class cl = Counter.class; public synchronized void increment() { String tname = Thread.currentThread().getName(); System.out.printf("%s: %d\n", tname, count++); } @Override public void run() { String tname = Thread.currentThread().getName(); while (true) { increment(); synchronized (Counter.class) { try { cl.notify(); cl.wait(); } catch (Exception e) { e.printStackTrace(); } } } } } public class WaitNotify { public static void main(String[] args) { Counter c = new Counter(); Thread t1 = new Thread(c, "thread1"); Thread t2 = new Thread(c, "thread2"); t1.start(); t2.start(); } } 

Ecco la mia soluzione senza attese o notifiche. wait () e notify () / notifyAll (),
Non vedo alcun motivo per usarli per questa affermazione problematica.

 package threading; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class EvenOddPrinting { int count=0; boolean isOdd = false; public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); EvenOddPrinting obj = new EvenOddPrinting(); exec.submit(new EvenPrinter(obj)); exec.submit(new OddPrinter(obj)); exec.shutdown(); } } class EvenPrinter implements Runnable{ EvenOddPrinting obj; public EvenPrinter(EvenOddPrinting obj) { this.obj=obj; } @Override public void run() { while(obj.count < 100){ if(!obj.isOdd){ System.out.println("Even:"+obj.count); obj.count++; obj.isOdd = true; } } } } class OddPrinter implements Runnable{ EvenOddPrinting obj; public OddPrinter(EvenOddPrinting obj) { this.obj = obj; } @Override public void run() { while(obj.count < 100){ if(obj.isOdd){ System.out.println("Odd:"+obj.count); obj.count++; obj.isOdd = false; } } } } 

Il tuo codice è stato corretto usando l’interfaccia Lock:

 import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class NumberPrinter implements Runnable { private Lock lock; private Condition condition; private String type; private static boolean oddTurn = true; public NumberPrinter(String type, Lock lock, Condition condition) { this.type = type; this.lock = lock; this.condition = condition; } public void run() { int i = type.equals("odd") ? 1 : 2; while (i < = 10) { if (type.equals("odd")) printOdd(i); if (type.equals("even")) printEven(i); i = i + 2; } } private void printOdd(int i) { // synchronized (lock) { lock.lock(); while (!oddTurn) { try { // lock.wait(); condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(type + " " + i); oddTurn = false; // lock.notifyAll(); condition.signalAll(); lock.unlock(); } // } private void printEven(int i) { // synchronized (lock) { lock.lock(); while (oddTurn) { try { // lock.wait(); condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(type + " " + i); oddTurn = true; // lock.notifyAll(); condition.signalAll(); lock.unlock(); } // } public static void main(String[] args) { Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); Thread odd = new Thread(new NumberPrinter("odd", lock, condition)); Thread even = new Thread(new NumberPrinter("even", lock, condition)); odd.start(); even.start(); } } 
 public class Number_Thread extends Thread { String thread; int limit; public Number_Thread(String thread,int limit){ this.thread=thread; this.limit=limit; } Object lock=new Object(); public void run() { synchronized (lock) { //------------------- "print even"--------------------// if(thread.equals("even")) { for (int i = 2; i < =limit; i+=2) { System.out.println(thread+" thread "+i); try { lock.wait(1000); continue; } catch (InterruptedException e) {} } lock.notifyAll(); } //------------------- "print odd"--------------------// if(thread.equals("odd")) { for (int i = 1; i <=limit; i+=2) { System.out.println(thread+" thread "+i); try { lock.wait(1000); continue; } catch (InterruptedException e) {} } lock.notifyAll(); } } } } //------------------thread creater class------------------// import java.util.Scanner; public class Main_Thread { private static Scanner s; public static void main(String[] args) throws InterruptedException { System.out.print("enter limit:\t "); s=new Scanner(System.in); int n=s.nextInt(); s.close(); Thread t1=new Number_Thread("even",n); Thread t2=new Number_Thread("odd",n); t2.start(); Thread.sleep(100); t1.start(); } } 

uscita per limite 5:

inserire il limite: 5

thread dispari 1

anche thread 2

thread dispari 3

anche thread 4

thread dispari 5

Ho implementato in questo modo, in base all’argomento, non verrà generato alcun thread e il rispettivo no in round round robin. cioè, se il numero di thread è 3, il thread 1 stamperà 1,4 …; il thread 2 stamperà 2,5, … e il thread 3 stamperà 3,6 …

 public class ThreadSynchronizer { public static void main(String[] args) { // BASED ON THE ARGUMENT MULTIPLE THREADS WILL BE CREATED AND EACH WILL PRINT ITS RESPECTIVE NO // IE, IF THREAD COUNT IS 3, THREAD 1 WILL PRINT 1,4 ..., THREAD2 WILL PRINT 2,5,... AND THREAD3 WILL PRINT 3,6... // LIMITED THE DISPLAY TO 1000 NOS int threadCnt = Integer.parseInt(args[0]); ReentrantLock lckArray[] = new ReentrantLock[threadCnt + 1]; for (int i = 0; i < threadCnt + 1; i++) { ReentrantLock lck = new ReentrantLock(); lck.lock(); lckArray[i] = lck; } for (int i = 0; i < threadCnt; i++) { Thread th = new Thread(new Printer(lckArray, i + 1)); th.start(); } for (int i = 1; i < threadCnt + 1; i++) { lckArray[i].unlock(); while (!lckArray[i].isLocked()) { } } lckArray[0].unlock(); } } class Printer implements Runnable { private ReentrantLock[] lckArray; private int index; Printer(ReentrantLock[] lckArray, int startValue) { this.lckArray = lckArray; this.index = startValue; } @Override public void run() { ReentrantLock prevLock = null; int printCounter = index; for (int counter = 0; printCounter <= 1000; counter++) { int remCounter = counter % lckArray.length; int incCounter = lckArray.length - remCounter; int indexPostion = index + incCounter; int curElementIndex = indexPostion % lckArray.length; lckArray[curElementIndex].lock(); if (prevLock != null) prevLock.unlock(); prevLock = lckArray[curElementIndex]; if (curElementIndex == 0) { System.out.println("Printed by Thread " + index + " " + printCounter); printCounter = printCounter + lckArray.length - 1; } } if (prevLock != null) { if (prevLock.isHeldByCurrentThread()) prevLock.unlock(); } } }