Today I started to study multithreading on java, I do not understand why the program in some cases gives the correct result, and in the rest deadlock.

The challenge is to provide reusable console output first with "I throw a ball" and then "I got a ball" using wait and notify. It is also necessary to get the correct result regardless of which thread of execution starts first.

package main; import java.util.Random; public class main { public static void main(String[] args) throws InterruptedException { NBAPlayer Oneil = new NBAPlayer(); Sender sender = new Sender(Oneil); Getter getter = new Getter(Oneil); for (int i = 0; i < 6; i++) { Thread t = new Thread(sender,"sender "); Thread th = new Thread(getter,"getter ");t.start(); Random random = new Random(); Thread.sleep(random.nextInt(500)+500); th.start(); } } static class Sender implements Runnable { NBAPlayer Oneil ; public Sender(NBAPlayer oneil) { Oneil = oneil; } public void run() { try { Oneil.throwBall(); } catch (InterruptedException e) { e.printStackTrace(); } } } static class Getter implements Runnable { NBAPlayer Oneil ; public Getter(NBAPlayer oneil) { Oneil = oneil; } public void run() { try { Oneil.getBall(); } catch (InterruptedException e) { e.printStackTrace(); } } } static class NBAPlayer { public volatile boolean ready = false; public synchronized void throwBall() throws InterruptedException { while(ready==false) { System.out.println("I throw a ball"); ready=true; notify(); } } public synchronized void getBall() throws InterruptedException { while(ready==false) { wait(); } System.out.println("I got your ball"); ready=false; } } } 
  • This is a classic producer-consumer task. Sheldt has it very well and in detail painted. - post_zeew
  • 3
    Think about what happens if two Sender threads work in a row. - Pavel Mayorov

1 answer 1

The answer was found in the book by Herbert Shildt - "Java 8. The Complete Guide."

 package main; import java.util.Random; public class main { public static void main(String[] args) throws InterruptedException { NBAPlayer Oneil = new NBAPlayer(); Sender sender = new Sender(Oneil); Getter getter = new Getter(Oneil); for (int i = 0; i < 6; i++) { Thread t = new Thread(sender, "sender "); Thread th = new Thread(getter, "getter "); t.start(); Random random = new Random(); Thread.sleep(random.nextInt(500) + 500); th.start(); } } static class Sender implements Runnable { NBAPlayer Oneil; public Sender(NBAPlayer oneil) { Oneil = oneil; } public void run() { try { Oneil.throwBall(); } catch (InterruptedException e) { e.printStackTrace(); } } } static class Getter implements Runnable { NBAPlayer Oneil; public Getter(NBAPlayer oneil) { Oneil = oneil; } public void run() { try { Oneil.getBall(); } catch (InterruptedException e) { e.printStackTrace(); } } } static class NBAPlayer { public volatile boolean ready = false; public synchronized void throwBall() throws InterruptedException { while (ready) { wait(); } System.out.println("I throw a ball"); ready = true; notify(); } public synchronized void getBall() throws InterruptedException { while (!ready) { wait(); } System.out.println("I got a ball"); ready = false; notify(); } } } 
  • while (ready == false) - why? - this is an obvious boolean type, why compare it? while (! ready). - And
  • You are right, no reason, the matter is my inexperience. I'll fix it now. - Bogdan Fishing