This week's book giveaway is in the Java in General forum.
We're giving away four copies of Helidon Revealed: A Practical Guide to Oracle’s Microservices Framework and have Michael Redlich on-line!
See this thread for details.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Liutauras Vilda
  • Ron McLeod
Sheriffs:
  • Jeanne Boyarsky
  • Devaka Cooray
  • Paul Clapham
Saloon Keepers:
  • Scott Selikoff
  • Tim Holloway
  • Piet Souris
  • Mikalai Zaikin
  • Frits Walraven
Bartenders:
  • Stephan van Hulst
  • Carey Brown

Threads and ActionListeners

 
Ranch Hand
Posts: 529
C++ Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am trying to understand Threads, so I wrote some code that I will play around with because the best way to learn for me is by experimenting...... Anyway, I have 2 text fields each with a counter in them. The counters are each in there own run method. I want to be able to stop and start them with 2 ActionListeners attached to 2 Buttons. When I run the program, the ActionListeners are not doing their job. Is it because the run methods are in an endless loop? How can I fix this problem? Thanks in advance!!! Here is the code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class Test9099 extends Thread
{
int counter1 = 0;
TextField field1;
TextField field2;
Thread t,c;
JButton pauseButton;
JButton resumeButton;

Test9099()
{
JFrame theFrame = new JFrame();
field1 = new TextField(10);
field2 = new TextField(10);
pauseButton = new JButton("Pause");
resumeButton = new JButton("Resume");

pauseButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
System.out.println("Pause Button Pressed");
try
{
t.wait();
c.wait();
}
catch (InterruptedException ie)
{
}
}
});
resumeButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
t.notify();
c.notify();
}
});


Container c = theFrame.getContentPane();
c.setLayout(new BorderLayout());

c.add(field1,"East");
c.add(field2,"West");
c.add(pauseButton,"North");
c.add(resumeButton,"South");


theFrame.setSize(400,400);
theFrame.show();

t = new Thread(this);
t.start();

}
public synchronized void run()
{
while (true)
{
counter1++;
String str = "" + counter1;
field1.setText(str);
System.out.println(str);
try
{
c.notify();
}
catch (Exception e)
{
e.printStackTrace();
}
t.yield();
}//end of while
}//end of run

class Inner extends Thread
{
public Inner()
{
c = new Thread(this);
c.start();
}

public synchronized void run()
{
while(true)
{
int counter2 = counter1++;
String g = "" + counter2;
field2.setText(g);

try
{
c.wait();
}
catch (Exception e)
{
e.printStackTrace();
}
}//end of while
}//end of run()
}

public static void main(String[]args)
{
Test9099 a = new Test9099();
Test9099.Inner b = a.new Inner();
}
}
 
Ranch Hand
Posts: 221
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Barry;
Your code shows some of the same misunderstandings that I recently addressed in another thread; rather than give a long answer right away I'll ask you to read that thread for starters.
I don't think the following is what you're after, but... Your existing code can be made to work as you intended by
  • in the pause button's listener, replace the <code>wait</code> calls with <code>suspend</code> (you'll no longer need the <code>try</code> block).
  • in the resume button's listener, replace the <code>notify</code> calls with <code>resume</code>
  • and finally delete the entire <code>try...catch</code> block and its contents and the call to <code>yield</code> in both of the <code>run</code> methods.

  • Now, I probably shouldn't even have suggested this, because this is not the right way to do this, and not just because <code>suspend</code> and <code>resume</code> are deprecated.
    If you've got questions after reading the other thread, post back.
    jply

    [This message has been edited by Jerry Pulley (edited October 07, 2000).]
     
    Barry Andrews
    Ranch Hand
    Posts: 529
    C++ Java Ubuntu
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks for the info! I replaced the wait() and notify() with suspend() and resume(), and it worked. However, can you offer a little explanation why the other way would not work. I guess I am not yet understanding threads. I read the other posts, but I still do not understand why the ActionListeners were being ignored. Thanks for your time!
     
    Jerry Pulley
    Ranch Hand
    Posts: 221
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Barry;
    Sorry I've been slow answering your question. Your code displays a misunderstanding that I'd like to address, but your core question is very good and I had to work on it.
    First, about synchronization - here's how it works: You pick some object (not a thread, in general) on which you want your threads to sync. Usually, this object has data that shouldn't be modified by multiple threads simultaneously, or (as in this case) as a convenient "token" that each thread must hold in order to proceed. This object becomes your monitor; you use it in your <code>synchronized (monitorObject) {...}</code> statement. Each thread entering that statement must then obtain the monitor's lock before proceding. In your code, you're making the <code>JFrame</code> a thread (not a good design idea, a frame isn't a thread). You're also creating some other threads and calling <code>wait</code> and <code>notify</code> on them; these methods should be called on your monitor object. Reread the first few paragraphs of my first reply to the other post for better synopsis of synchronization.
    OK, with that out of the way, the other issue is not as basic. I think the problem here is the single-thread rule: When using Swing components all manipulation of the components (like calling <code>setText</code>) must occur within the AWT event thread. Even when I structured the synchronization correctly and used only AWT components, the buttons were ignored.
    Like I said, I had to work on it. I wrote an AWT-only program similar to yours and came up with a scheme to make it work; I'm going to start a new post to request comment on this scheme.
    Finally, I'd like to ask that you use either UBB [CODE] tags or (my preference) HTML < pre> and < code> tags to preserve your formatting; it's a lot of work reformatting code in an editor to analyze it.
    jply
     
    Barry Andrews
    Ranch Hand
    Posts: 529
    C++ Java Ubuntu
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks again for this information! You have been very helpful! Please forgive my ignorance, but what do you mean by using the <pre> and <code> tags?
     
    Politics n. Poly "many" + ticks "blood sucking insects". Tiny ad:
    Gift giving made easy with the permaculture playing cards
    https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
    reply
      Bookmark Topic Watch Topic
    • New Topic