Swing GUI freezing with the bounded-buffer problem

  • (2 Pages)
  • +
  • 1
  • 2

20 Replies - 1860 Views - Last Post: 30 July 2014 - 10:23 AM Rate Topic: -----

#1 pwm   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 12
  • Joined: 12-July 14

Swing GUI freezing with the bounded-buffer problem

Posted 12 July 2014 - 04:42 PM

Hi all,

i'm writing a simple application, that provides a Swing GUI to a bounded-buffer problem. The application is composed by:
- Main.java: it creates a map of four threads (four instances of the class MyThread). Also it creates a shared database (an instance of the class Database) between the four threads.
- MyThread.java: it's an extension of Thread, and it shows a Swing GUI associated to this thread. Each thread is associated a GUI.
- GUI.java
- Database.java: it's an extension of ArrayList and and it can contain a maximum of five elements. An element is an instance of the class User. Also it implements put() and extract() method consistent with the algorithm of bounded-buffer problem.
- DatabaseException.java: it's a simple message.
- User.java

public class Main {   
    public static void main(String[] args) {
        Database db = new Database();
        Map<String, Thread> tdg_m = new HashMap();  
        for (int i = 1; i <= 4; i++) {
            tdg_m.put("T" + i, new MyThread(db));
            tdg_m.get("T" + i).setName("T" + i);
            tdg_m.get("T" + i).start();
        }
    }  
}


public class MyThread extends Thread {
    
    private final Database db;

    MyThread(Database db) {
        this.db = db;
    }

    @Override
    public void run() {
        GUI gui = new GUI(db, Thread.currentThread());
        gui.setVisible(true);
        while(true) {          
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex);
            }   
        }
    }
    
}


public class GUI extends javax.swing.JFrame {
    private final Database db;
    private final Thread pt;

    public GUI(Database db, Thread pt) {
        initComponents(); 
        this.db = db;
        this.pt = pt;
        this.setTitle("MyThread - " + this.pt.getName());
    }

    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jLCodiceFiscale = new javax.swing.JLabel();
        jTFID = new javax.swing.JTextField();
        jLNome = new javax.swing.JLabel();
        jTFName = new javax.swing.JTextField();
        jBPut = new javax.swing.JButton();
        jBExtract = new javax.swing.JButton();
        jBShowDb = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setResizable(false);

        jLCodiceFiscale.setForeground(new java.awt.Color(255, 0, 0));
        jLCodiceFiscale.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLCodiceFiscale.setText("ID :");
        jLCodiceFiscale.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);

        jLNome.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLNome.setText("Name :");

        jBPut.setText("put");
        jBPut.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBPutActionPerformed(evt);
            }
        });

        jBExtract.setText("extract");
        jBExtract.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBExtractActionPerformed(evt);
            }
        });

        jBShowDb.setText("show db");
        jBShowDb.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBShowDbActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jLNome, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLCodiceFiscale, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                        .addComponent(jTFID, javax.swing.GroupLayout.DEFAULT_SIZE, 249, Short.MAX_VALUE)
                        .addComponent(jTFName, javax.swing.GroupLayout.Alignment.LEADING))
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                        .addComponent(jBShowDb, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 91, Short.MAX_VALUE)
                        .addComponent(jBPut, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jBExtract, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jTFID, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLCodiceFiscale, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jTFName, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLNome, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addComponent(jBPut)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jBExtract)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jBShowDb)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        

    private void jBShowDbActionPerformed(java.awt.event.ActionEvent evt) {                                         
        try {
            System.out.println("\nNumber of users: " + db.size() + "\n");
            db.show(System.out);
        } catch (DatabaseException ex) {
            JOptionPane.showMessageDialog(this, ex, "Message from " + pt.getName(), JOptionPane.INFORMATION_MESSAGE);
        }
    }                                        

    private void jBPutActionPerformed(java.awt.event.ActionEvent evt) {                                      
        User new_u = new User(jTFID.getText(), jTFName.getText());
        try {
            db.put(new_u);
        } catch (DatabaseException ex) {
            JOptionPane.showMessageDialog(this, ex, "Message from " + pt.getName(), JOptionPane.INFORMATION_MESSAGE);
        }
    }                                     

    private void jBExtractActionPerformed(java.awt.event.ActionEvent evt) {                                          
        User del_u;
        try {
            del_u = db.extract(jTFID.getText());
            System.out.println("Deleted user:\n");
            System.out.println(del_u.toString() + "\n-----\n");
        } catch (DatabaseException ex) {
            JOptionPane.showMessageDialog(this, ex, "Message from " + pt.getName(), JOptionPane.INFORMATION_MESSAGE);
        }
    }                                         

    // Variables declaration - do not modify                     
    private javax.swing.JButton jBExtract;
    private javax.swing.JButton jBPut;
    private javax.swing.JButton jBShowDb;
    private javax.swing.JLabel jLCodiceFiscale;
    private javax.swing.JLabel jLNome;
    private javax.swing.JTextField jTFID;
    private javax.swing.JTextField jTFName;
    // End of variables declaration                   

}


public class Database extends ArrayList<User> {

    final int DATABASE_SIZE = 5;

    public synchronized void put(User u) throws DatabaseException {
        while(this.size() == this.DATABASE_SIZE) {
            try {
                wait();
            } catch (InterruptedException ex) {
                Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        for (User curr_u : this) {
            if (curr_u.equals(u)) {          
                throw new DatabaseException("The user already exists in the database");
            }
        }
        this.add(u);
        notifyAll();
    }

    public synchronized User extract(String id) throws DatabaseException {
        while (this.isEmpty()) {
            try {
                wait();
            } catch (InterruptedException ex) {
                Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        for(User curr_u : this) {
            if(curr_u.getId().equals(id)) {
                this.remove(curr_u);
                notifyAll();
                return curr_u;
            }
        }
        throw new DatabaseException("The user is not present in the database");
    }

    public void show(PrintStream out) throws DatabaseException {
        if(this.isEmpty()) {
            throw new DatabaseException("The database is empty");
        }
        for(User curr_u : this) {
            System.out.println(curr_u.toString() + "\n-----");
        }
    }
    
}


public class DatabaseException extends Exception {

    public DatabaseException(String message) {
        super(message);
    }
    
}


public class User {
    private String id;
    private String name;
    
    public User(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public boolean equals(User u) {
        return(this.getId().equals(u.getId()));
    }
    
    @Override
    public boolean equals(Object u) {
        if(u == null) return false;
        if(u instanceof User) return(this.equals((User) u));
        return false;
    }
    
    @Override
    public String toString() {
        return (this.id + "\n" + this.name);
    }
    
}



The issue is the following. When the database is full, and i try to put an element, the GUI freezes. The same problem occurs when I try to extract an element from the empty database.

How i fix these issues ?

Thanks so much !

Is This A Good Question/Topic? 0
  • +

Replies To: Swing GUI freezing with the bounded-buffer problem

#2 CasiOo   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1577
  • View blog
  • Posts: 3,551
  • Joined: 05-April 11

Re: Swing GUI freezing with the bounded-buffer problem

Posted 12 July 2014 - 05:03 PM

Your GUI is event driven, and it is all happening on the EDT (event dispatch thread)
This means you should not be sleeping or doing any long running tasks on this thread, otherwise the GUI will become unresponsive
Your wait() calls in your Database class is making the EDT thread sleep

The solution is to call put and extract on a background thread
The background thread can then later on post a result to the EDT (You are only allowed to modify Swing components when on the EDT)

Check out ExectuorService and the helper class Executors to run tasks on a background thread
private ExecutorService es = Executors.newCachedThreadPool();

private void onPutClick(ActionEvent e) {
	final User new_u = new User(jTFID.getText(), jTFName.getText());
	es.submit(new Runnable() {
		public void run() {
			try {
				db.put(new_u);
			} catch (DatabaseException ex) {
				JOptionPane.showMessageDialog(this, ex, "Message from " + pt.getName(), JOptionPane.INFORMATION_MESSAGE);
			}
		}
	});
}



The SwingUtilities class have methods which can help you get back on the EDT and execute code :)
Was This Post Helpful? 3
  • +
  • -

#3 pwm   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 12
  • Joined: 12-July 14

Re: Swing GUI freezing with the bounded-buffer problem

Posted 13 July 2014 - 08:05 AM

Great !!!
It works fine!

About SwingUtilities, how i can fix the issue using the method EventQueue.invokeLater() ? I try to use it in the main() method, just to make visible the GUI, but the GUI already freezes.

Thanks
Was This Post Helpful? 0
  • +
  • -

#4 CasiOo   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1577
  • View blog
  • Posts: 3,551
  • Joined: 05-April 11

Re: Swing GUI freezing with the bounded-buffer problem

Posted 13 July 2014 - 08:39 AM

Very simple actually
The invokeAndWait method will be all you need. It then waits until the GUI becomes visible
    @Override
    public void run() {
		final String threadName = Thread.currentThread().getName();
		
		SwingUtilities.invokeAndWait(new Runnable() {
			public void run() {
				GUI gui = new GUI(db, threadName);
				gui.setVisible(true);
			}
		});
        
        while(true) {          
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex);
            }   
        }
    }



BUT!!
It kinda ruins the current design you have
If you use the ExecutorService example I showed you earlier, then the database put and extract will not be called on your MyThread thread ^^
Instead the ExecutorService uses a pooled thread, which you have not initialized or started yourself
Just keep that in mind :)
Was This Post Helpful? 1
  • +
  • -

#5 pwm   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 12
  • Joined: 12-July 14

Re: Swing GUI freezing with the bounded-buffer problem

Posted 13 July 2014 - 09:26 AM

Quote

BUT!!
It kinda ruins the current design you have
If you use the ExecutorService example I showed you earlier, then the database put and extract will not be called on your MyThread thread ^^
Instead the ExecutorService uses a pooled thread, which you have not initialized or started yourself
Just keep that in mind :)

Then the invokeAndWait() is what i need! :smile2:
Also, why you use invokeAndWait() instead InvokeLater() ?

But i try to add your code and the issue is the same. This is MyThread class after the latest modify:
public class MyThread extends Thread {

    private final Database db;
    private final Thread this_thread;

    MyThread(Database db) {
        this.db = db;
        this.this_thread = this;
    }

    @Override
    public void run() {
        
        try {
            SwingUtilities.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    GUI gui = new GUI(db, this_thread);
                    gui.setVisible(true);
                }
            });
        } catch (InterruptedException ex) {
            Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvocationTargetException ex) {
            Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex);
        }

        while (true) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

}


Thanks
Was This Post Helpful? 0
  • +
  • -

#6 CasiOo   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1577
  • View blog
  • Posts: 3,551
  • Joined: 05-April 11

Re: Swing GUI freezing with the bounded-buffer problem

Posted 13 July 2014 - 10:42 AM

When does your GUI become unresponsive?
I just tried and copy the code, and it seems to be showing the window and all
I didn't try click the buttons though

Can I have some more details on how it is not working as expected please :)
Supply your new code if needed

This post has been edited by CasiOo: 13 July 2014 - 10:42 AM

Was This Post Helpful? 0
  • +
  • -

#7 pwm   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 12
  • Joined: 12-July 14

Re: Swing GUI freezing with the bounded-buffer problem

Posted 13 July 2014 - 10:56 AM

With the invokeAndWait() method, the GUI become unresponsive when I press put button and the database is full, and when I press extract button and the database is empty. This happens if you use the code I posted at the beginning and change only the MyThread class (which is the last one I posted).
Was This Post Helpful? 0
  • +
  • -

#8 CasiOo   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1577
  • View blog
  • Posts: 3,551
  • Joined: 05-April 11

Re: Swing GUI freezing with the bounded-buffer problem

Posted 13 July 2014 - 11:28 AM

That's because the problem you have in your MyThread class has nothing to do with the problem found in your GUI class
The type of problem is the same, but one magic trick won't solve them both at the same time

Please remember that your GUI will only run on the EDT. You can't run your GUI on multiple threads
The event handlers however can start tasks on new threads, and later on post a result to the EDT
Was This Post Helpful? 0
  • +
  • -

#9 pwm   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 12
  • Joined: 12-July 14

Re: Swing GUI freezing with the bounded-buffer problem

Posted 13 July 2014 - 11:38 AM

So, can't I make visible MyThread's GUI on MyThread itself ?
Was This Post Helpful? 0
  • +
  • -

#10 CasiOo   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1577
  • View blog
  • Posts: 3,551
  • Joined: 05-April 11

Re: Swing GUI freezing with the bounded-buffer problem

Posted 13 July 2014 - 11:54 AM

Here is a resource from Oracle that explains how threading in Swing works
Read the whole tutorial, especially the The Event Dispatch Thread part
Was This Post Helpful? 1
  • +
  • -

#11 pwm   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 12
  • Joined: 12-July 14

Re: Swing GUI freezing with the bounded-buffer problem

Posted 14 July 2014 - 12:05 PM

Hi CasiOo,

I read the whole article, and I've understand that i must use SwingWorker. In particularly, i must use the SwingWorker's doInBackground() method. But, I don't understand if SwingWorker replaces MyThread, or SwingWorker starts MyThread's object (that are thread). The exercise specifies that there must be four threads. How i can implements SwingWorker in this way ?

Thanks so much, again!
Was This Post Helpful? 0
  • +
  • -

#12 pwm   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 12
  • Joined: 12-July 14

Re: Swing GUI freezing with the bounded-buffer problem

Posted 14 July 2014 - 01:33 PM

I try to modify the app, using SwingWorker. The app seems to work, but not in the way specified from the exercise. In fact, the methods put() and extract() are not performed by the four MyThread's obecjects. I've created two class, PutWorker and ExtractWorked, that are used in GUI:

package my_producer_consumer;

import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class PutWorker extends SwingWorker {

    private final Database db;
    private final User new_u;
    private final MyThread pt;

    public PutWorker(Database db, User new_u, MyThread pt) {
        this.db = db;
        this.new_u = new_u;
        this.pt = pt;
    }

    @Override
    protected Database doInBackground() throws Exception {
        try {
            db.put(new_u);
            // temp
            System.out.println("EDT ? " + SwingUtilities.isEventDispatchThread());
            System.out.println(Thread.currentThread().getName() + " running ...");
        } catch (DatabaseException ex) {
            System.out.println("\nMessage from thread " + pt.getName());
            System.out.println(ex + "\n");
        }
        return db;
    }

}


package my_producer_consumer;

import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class ExtractWorker extends SwingWorker<Database, Void> {

    private final Database db;
    private final String id;
    private final MyThread pt;

    public ExtractWorker(Database db, String id, MyThread pt) {
        this.db = db;
        this.id = id;
        this.pt = pt;
    }

    @Override
    protected Database doInBackground() throws Exception {
        try {
            User del_u = db.extract(id);
            System.out.println("\nDeleted user:\n");
            System.out.println(del_u.toString() + "\n-----\n");
            // temp
            System.out.println("EDT ? " + SwingUtilities.isEventDispatchThread());
            System.out.println(Thread.currentThread().getName() + " running ...");
            return db;
        } catch (DatabaseException ex) {
            System.out.println("\nMessage from thread " + pt.getName());
            System.out.println(ex + "\n");
        }
        return db;
    }

}


The new GUI class:

package my_producer_consumer;

import javax.swing.JOptionPane;

public class GUI extends javax.swing.JFrame {

    private final Database db;
    private final MyThread pt;

    public GUI(Database db, MyThread pt) {
        initComponents();
        this.db = db;
        this.pt = pt;
        this.setTitle("MyThread - " + pt.getName());
    }

    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jLCodiceFiscale = new javax.swing.JLabel();
        jTFID = new javax.swing.JTextField();
        jLNome = new javax.swing.JLabel();
        jTFName = new javax.swing.JTextField();
        jBPut = new javax.swing.JButton();
        jBExtract = new javax.swing.JButton();
        jBShowDb = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setResizable(false);

        jLCodiceFiscale.setForeground(new java.awt.Color(255, 0, 0));
        jLCodiceFiscale.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLCodiceFiscale.setText("ID :");
        jLCodiceFiscale.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);

        jLNome.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLNome.setText("Name :");

        jBPut.setText("put");
        jBPut.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBPutActionPerformed(evt);
            }
        });

        jBExtract.setText("extract");
        jBExtract.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBExtractActionPerformed(evt);
            }
        });

        jBShowDb.setText("show db");
        jBShowDb.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBShowDbActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jLNome, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLCodiceFiscale, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                        .addComponent(jTFID, javax.swing.GroupLayout.DEFAULT_SIZE, 249, Short.MAX_VALUE)
                        .addComponent(jTFName, javax.swing.GroupLayout.Alignment.LEADING))
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                        .addComponent(jBShowDb, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 91, Short.MAX_VALUE)
                        .addComponent(jBPut, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jBExtract, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jTFID, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLCodiceFiscale, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jTFName, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLNome, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addComponent(jBPut)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jBExtract)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jBShowDb)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        

    private void jBShowDbActionPerformed(java.awt.event.ActionEvent evt) {                                         
        try {
            db.show(System.out);
            System.out.println("\nNumber of users: " + db.size() + "\n");
        } catch (DatabaseException ex) {
            JOptionPane.showMessageDialog(this, ex, "Message from " + pt.getName(), JOptionPane.INFORMATION_MESSAGE);
        }
    }                                        

    private void jBPutActionPerformed(java.awt.event.ActionEvent evt) {                                      
        User new_u = new User(jTFID.getText(), jTFName.getText());
        PutWorker pw = new PutWorker(db, new_u, pt);
        pw.execute();
    }                                     

    private void jBExtractActionPerformed(java.awt.event.ActionEvent evt) {                                          
        ExtractWorker ew = new ExtractWorker(db, jTFID.getText(), pt);
        ew.execute();
    }                                         

    // Variables declaration - do not modify                     
    private javax.swing.JButton jBExtract;
    private javax.swing.JButton jBPut;
    private javax.swing.JButton jBShowDb;
    private javax.swing.JLabel jLCodiceFiscale;
    private javax.swing.JLabel jLNome;
    private javax.swing.JTextField jTFID;
    private javax.swing.JTextField jTFName;
    // End of variables declaration                   

}


Was This Post Helpful? 0
  • +
  • -

#13 pwm   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 12
  • Joined: 12-July 14

Re: Swing GUI freezing with the bounded-buffer problem

Posted 14 July 2014 - 01:39 PM

In PutWorker, the code:
// temp
System.out.println("EDT ? " + SwingUtilities.isEventDispatchThread());
System.out.println(Thread.currentThread().getName() + " running ...")



must be print:
"EDT ? false"
"T2 running ..."
for example.
Was This Post Helpful? 0
  • +
  • -

#14 CasiOo   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1577
  • View blog
  • Posts: 3,551
  • Joined: 05-April 11

Re: Swing GUI freezing with the bounded-buffer problem

Posted 14 July 2014 - 03:25 PM

Using a SwingWorker is a great idea.. Usually..
The main difficulty for you, is controlling which thread will execute the task
You also want to make sure that the same threads are being reused.. This is rather difficult as well
It is tricky and difficult because the Java API wants to hide all that stuff away from you by using thread pools and what not
Usually you would let others handle which thread will be executing the task, and you just tell how many threads can be used or how to create the threads

You could start coding additional functionality on top of the thread class to execute tasks as they become available
I wouldn't go that route since it is complex and requires to be thought through and tested carefully. Not the easiest!

You can however, through the Java API, create an Executor that only uses a single thread
It is not guaranteed that the same thread will be reused at all times.. At failure, the Executor might just create a new thread for example :)
Though it is worth a shot
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;


public class Snippet {

	public static void main(String[] args) throws InterruptedException {
		//Setup executors
		ExecutorService es1 = Executors.newSingleThreadExecutor(new NamedThreadFactory("Thread1"));
		ExecutorService es2 = Executors.newSingleThreadExecutor(new NamedThreadFactory("Thread2"));
		
		//Run tasks
		es1.execute(new Runnable() {
			public void run() {
				System.out.println("Long running task at " + Thread.currentThread().getName());
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});
		
		es1.execute(new Runnable() {
			public void run() {
				System.out.println("Short running task at " + Thread.currentThread().getName());
			}
		});
		
		es2.execute(new Runnable() {
			public void run() {
				System.out.println("Short running task at " + Thread.currentThread().getName());
			}
		});

		//Wait for termination
		es1.shutdown();
		es2.shutdown();
		es1.awaitTermination(10, TimeUnit.SECONDS);
		es2.awaitTermination(10, TimeUnit.SECONDS);
		System.out.println("terminated");
	}

	public static class NamedThreadFactory implements ThreadFactory {
		private String name;
		
		public NamedThreadFactory(String name) {
			this.name = name;
		}
		
		@Override
		public Thread newThread(Runnable r) {
			System.out.println("Creating thread: " + name);
			Thread thread = new Thread(r);
			thread.setName(name);
			return thread;
		}
	}
}


Luckily it seems like the same thread is being reused :)
Output:
Creating thread: Thread1
Long running task at Thread1
Creating thread: Thread2
Short running task at Thread2
Short running task at Thread1
terminated


Was This Post Helpful? 1
  • +
  • -

#15 pwm   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 12
  • Joined: 12-July 14

Re: Swing GUI freezing with the bounded-buffer problem

Posted 14 July 2014 - 05:07 PM

so ... is it impossible rewrite the app in another way, without using ExecutorService, in order to meet the delivery?
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2