0

I have this problem on this exercise where I have 3 classes, a Provider(Thread) that keeps providing Integer products stored inside a LinkedList. Once it reaches size 10 at least, Retailers(Thread) can buy them all. And there is the Distributor which is coordinating the threads. The products are displayed on a JFrame, and then when I click the Stop button, every thread stops and each retailer tells how many products they bought.

EDIT: Forgot to put the problem, everytime I click on the Stop button, the applciation freezes and I cant even close the JFrame window, dont understand why.

 public class Distributor {

    private JTextField textfield = new JTextField();
    private LinkedList<Integer> productList = new LinkedList<Integer>();
    private JFrame frame = new JFrame("Window");
    private JButton btn = new JButton("Stop");
    private Thread provider = new Thread(new Provider(this));
    private LinkedList<Thread> retailerList = new LinkedList<Thread>();

    private void addRetailer(int num) {
        for (int i = 0; i < num; i++)
            retailerList.add(new Thread(new Retailer(i, this)));
    }

    public Distributor() {
        frame.setSize(300, 200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.add(textfield);
        frame.add(btn, BorderLayout.SOUTH);
        addRetailer(2);


        btn.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    provider.interrupt();
                    provider.join();
                    System.out.println(provider.isAlive());

                    for (Thread t : retailerList) {
                        t.interrupt();
                        t.join();
                        System.out.println(t.isAlive());
                    }
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }
        });
    }

    public void execute() {
        frame.setVisible(true);
        provider.start();
        for (Thread t : retailerList)
            t.start();
    }

    // Keeps providing products, and notifies retailers when there are 10 products
    public synchronized void provide(int product) {
        textfield.setText(productList.toString());
        productList.add(product);
        if (productList.size() == 10)
            notifyAll();
    }

    // Sells all the products if there are at least 10 to sell.
    public synchronized int sell() throws InterruptedException {
        while (productList.size() < 10)
            wait();

        int total = productList.size();
        notifyAll();
        textfield.setText(productList.toString());
        productList.clear();
        return total;
    }
}

The Provider class:

public class Provider implements Runnable {
private Distributor distribuidor;
private int total = 0;

public Provider(Distributor distribuidor) {
    super();
    this.distribuidor = distribuidor;
}

@Override
public void run() {
    while (!Thread.interrupted()) {
        try {
            distribuidor.provide((int) (Math.random() * 10) + 1);
            Thread.sleep(10);
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
    System.out.println("Provider Interrupted");
 }
}

Retailer class:

public class Retailer implements Runnable {

private Distributor distributor;
private int total = 0;
private int id;

public Retailer(int id, Distributor distributor) {
    super();
    this.id = id;
    this.distributor = distributor;
}

@Override
public void run() {
    while (!Thread.interrupted()) {
        try {
            total += distributor.sell();
            Thread.sleep(10);
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
    System.out.println("Retailer id: " + id + " bought: " + total + " products");
 }
}

And the main class:

public class Main {
    public static void main(String[] args) {
        Distributor distributor = new Distributor();
        distributor.execute();
    }
}
jruivo
  • 447
  • 1
  • 8
  • 22
  • Ops sorry my bad, the problem is that everytime I click on the Stop button, it's supposed to interrupt the threads, but Frame freezes and nothing happens. The application cant even be closed, gotta do it through Task Manager. – jruivo Nov 14 '15 at 11:43
  • You're blocking the EDT. See also [`java.util.concurrent`](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html), for [example](http://stackoverflow.com/a/11372932/230513) – trashgod Nov 14 '15 at 11:51

2 Answers2

1

The problem is that your Thread is actually never stopping and the EDT is being blocked also.

I'd suggest you use a boolean to stop your infinite loop inside of Provider.


Provider

class Provider implements Runnable {
    private Distributor distribuidor;
    private int total = 0;
    private boolean isRunning = true;

    public void setIsRunning(boolean bool){
        isRunning = bool;
    }

    public Provider(Distributor distribuidor) {
        super();
        this.distribuidor = distribuidor;
    }

    @Override
    public void run() {
        while (isRunning) {
            try {
                distribuidor.provide((int) (Math.random() * 10) + 1);
                Thread.sleep(1000);
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
        System.out.println("Provider Interrupted");
    }
}

And in your Distributor class, change the following :

private Provider pro = new Provider(this);
private Thread provider = new Thread(pro);

and

btn.addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
        try {
            pro.setIsRunning(false);
            provider.interrupt();
            provider.join();
            System.out.println(provider.isAlive());

            for (Thread t : retailerList) {
                t.interrupt();
                t.join();
                System.out.println(t.isAlive());
            }
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
    }
});

Output after clicking on the Stop Button

enter image description here

Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
1

Don't catch InterruptedException inside the loop, instead put the loop inside the try { ... }

Provider Class:

public class Provider implements Runnable {

    private Distributor distribuidor;
    private int total = 0;

    public Provider(Distributor distribuidor) {
        super();
        this.distribuidor = distribuidor;
    }

    @Override
    public void run() {
        try {
            while (!Thread.currentThread().isInterrupted()) {
                distribuidor.provide((int) (Math.random() * 10) + 1);
                Thread.sleep(10);
            }
        } catch (InterruptedException interruptedException) {
        }
        System.out.println("Provider Interrupted");
    }
}

Retailer Class:

public class Retailer implements Runnable {

    private Distributor distributor;
    private int total = 0;
    private int id;

    public Retailer(int id, Distributor distributor) {
        super();
        this.id = id;
        this.distributor = distributor;
    }

    @Override
    public void run() {
        try {
            while (!Thread.currentThread().isInterrupted()) {
                total += distributor.sell();
                Thread.sleep(10);
            }
        } catch (InterruptedException interruptedException) {
        }
        System.out.println("Retailer id: " + id + " bought: " + total + " products");
    }
}
WillShackleford
  • 6,918
  • 2
  • 17
  • 33