This question already has answers here:
Stopping a Thread in Java? [duplicate]
(3 answers)
Closed 9 years ago.
I am trying to create a thread for a specific task to run in another class. The thread is starting the task but when I try to stop the thread, it is not stopping. The thread continues till the loop. Could you please help me out.
Thread Class:
package com.development;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ThreadExample extends JFrame {
MyThread mt;
Thread th;
ThreadExample(){
JPanel p1 = new JPanel();
p1.setPreferredSize(new Dimension(400,400));
JButton b1 = new JButton("Start");
JButton b2 = new JButton("Stop");
b1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
mt = new MyThread();
th = new Thread(mt);
th.start();
}
});
b2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
th.interrupt();
}
});
p1.add(b1);
p1.add(b2);
this.getContentPane().add(p1);
this.pack();
this.setVisible(true);
}
public static void main(String arg[]) {
ThreadExample mt = new ThreadExample();
mt.setVisible(true);
}
public class MyThread implements Runnable{
private volatile boolean runnable=true;
DisplayMsg dm = new DisplayMsg("Cycle");
#Override
public void run() {
while(!Thread.currentThread().isInterrupted()) {
// TODO Auto-generated method stub
dm.show();
}
}
}
}
DisplayMsg class:
package com.development;
public class DisplayMsg {
private String dispMsg;
private boolean runnable;
DisplayMsg(String dispMsg){
this.dispMsg=dispMsg;
}
public void show() {
for(int t=0;t<100;t++) {
try {
System.out.println(dispMsg + t);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Your DisplayMsg class loops for 100 seconds, and ignores interrupts. Indeed, when Thread.sleep() is interrupted, it resets the interrupt status, then throws an InterruptedException. Since you ignore the InterruptedException, the thread continues as if nothing happened.
public void show() {
for(int t=0;t<100;t++) {
try {
System.out.println(dispMsg + t);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Don't ignore interrupts:
public void show() {
for(int t=0;t<100;t++) {
try {
System.out.println(dispMsg + t);
Thread.sleep(1000);
} catch (InterruptedException e) {
// re-interrupt the thread and stop looping
Thread.currentThread().interrupt();
return;
}
}
}
A much simpler design which achieves what you need is the following:
public class MyThread implements Runnable{
DisplayMsg dm = new DisplayMsg("Cycle");
#Override public void run() {
try { while(true) dm.show(); }
catch (InterruptedException e) { }
}
}
public class DisplayMsg {
...
public void show() throws InterruptedException {
for(int t=0;t<100;t++) {
System.out.println(dispMsg + t);
Thread.sleep(1000);
}
}
}
This will simply let the InterruptedException propagate and end MyThread, with no effort on your own.
When you catch the InterruptedException in your DisplayMsg class, the interrupted flag is reset.
It's fine to catch the exception, but if you need to subsequently know if the thread has been interrupted, you need to reset the flag by interrupting again with Thread.currentThread.interrupt(); in that catch block and break out of the loop / return.
I believe what is happening is that you need to be checking !Thread.currentThread().isInterrupted() before each sleep. You are calling show() in the method which will iterate for 100 seconds only then will the your while loop check to see if the thread is interrupted. Move your check for interrtuped to your show method and see if it sees the interrupted flag. As per the next answers you should also set the Thread interrupted flag when you catch the InterruptedException.
Related
I have looked everywhere. How to suspend/pause it by code until I call it to awake using any java.util.concurrentmethods/objects? I have simple Thread with run method:
When I press button it stops then starts but the problem is that I get exception when I start it again. I want it play/pause like in the media player.
Exception in thread "AWT-EventQueue-0" java.lang.IllegalMonitorStateException
Full working code(with exceptions):
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class Window extends JFrame {
ThreadPanel leftPanel, rightPanel;
Thread leftThread, rightThread;
public Window() {
super("StopResume");
}
public void createGUI() {
setLayout(new GridLayout());
add(leftPanel = new ThreadPanel());
add(rightPanel = new ThreadPanel());
leftThread = new Thread(leftPanel);
rightThread = new Thread(rightPanel);
leftThread.start();
rightThread.start();
setSize(800, 600);
setVisible(true);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
int confirmed = JOptionPane.showConfirmDialog(null, "Zamknąć", "Potwierdzenie", JOptionPane.OK_CANCEL_OPTION);
if (confirmed == JOptionPane.OK_OPTION) {
dispose();//tu podmienic kod
System.exit(1);
}
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Window().createGUI();
}
});
}
}
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class ThreadPanel extends JPanel implements Runnable {
public static final String SUSPENDED = "GO", RUNNING = "SUSPEND";
JTextArea txt;
JButton ppButton;
DateFormat dateFormat;
Lock lock;
Condition cond;
boolean running;
public ThreadPanel() {
super();
createGUI();
dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
lock = new ReentrantLock();
cond = lock.newCondition();
running = true;
}
public void createGUI() {
setLayout(new BorderLayout());
JScrollPane jsp = new JScrollPane(txt = new JTextArea(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
add(jsp, BorderLayout.CENTER);
add(ppButton = new JButton(RUNNING), BorderLayout.SOUTH);
ppButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println(1);
if (running) {
running = false;
ppButton.setText(SUSPENDED);
} else {
running = true;
ppButton.setText(RUNNING);
lock.unlock();
}
lock.lock();
if (!running) {
cond.signalAll();
}
lock.unlock();
}
});
}
#Override
public void run() {
while (true) {
lock.lock();
try {
if (!running)
cond.await();
} catch (Exception e) {
e.printStackTrace();
}
Calendar cal = Calendar.getInstance();
txt.append("\n" + dateFormat.format(cal.getTime()));
try {
Thread.sleep((long) (Math.random() * 1001 + 500));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(2);
lock.unlock();
}
}
}
I see you want a button to start and stop the thread. So basically you need to in the actionPerformed(), acquire the lock, look up the state of things, manipulate the state, tell the waiting entity that something changed, and then release all your locks.
The Runnable thread (for lack of a label) should remain mostly unchanged but should check the Condition within a loop to avoid the case where your signalAll() wakes and the Condition still is not symenticly true or false. (signal() and signalAll() are not guaranteed to be sync right after the lock is released, so 2 calls to actionPerformed() may have happened already).
public void createGUI() {
setLayout(new BorderLayout());
JScrollPane jsp = new JScrollPane(txt = new JTextArea(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
add(jsp, BorderLayout.CENTER);
add(ppButton = new JButton(RUNNING), BorderLayout.SOUTH);
ppButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// This is where we acquire the lock to safely look at the state
lock.lock();
System.out.println(1);
// Manipulate the state
if (running) {
running = false;
ppButton.setText(SUSPENDED);
} else {
running = true;
ppButton.setText(RUNNING);
}
// Signal that this conditional changed (is either true or false now)
cond.signalAll();
// Release the lock so other entities can go forward
lock.unlock();
}
});
}
#Override
public void run() {
while (true) {
lock.lock();
try {
// This should block until this condition is true with a loop
while (!running)
cond.await();
} catch (Exception e) {
e.printStackTrace();
}
Calendar cal = Calendar.getInstance();
txt.append("\n" + dateFormat.format(cal.getTime()));
// No need to sleep()
System.out.println(2);
lock.unlock();
}
}
}
One way to do what I think you're asking for is to use a CyclicBarrier (from java.util.concurrent), parameterising it with two "parties".
The first thread to call await on the barrier will be suspended/blocked until a second thread also calls await, at which point both threads can proceed.
Here's a simple code sample:
import java.util.concurrent.CyclicBarrier;
public class Test {
public static void main(String[] args) {
// a barrier requiring two threads to call await before
// any thread can proceed past the barrier
final CyclicBarrier barrier = new CyclicBarrier(2);
new Thread(){
#Override
public void run() {
try {
// do some stuff
System.out.println("in thread, before the barrier");
// calling await blocks until two threads
// (this one and one other) have called await
barrier.await();
// do some more stuff
System.out.println("in thread, after the barrier");
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
try {
System.out.println("main thread, before barrier");
// calling await blocks until two threads
// (this one and one other) have called await
barrier.await();
System.out.println("main thread, after barrier");
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
I have already seen this question : How pause and then resume a thread?
I have seen many questions in stackoverflow related to my issue, but I couldn't understand them because they are abstract and not specific enough to my sitiuation.
There are 2 Count Down Labels. When you click Start Button, the countdown is executed. In the same way, when you click Pause Button, it should be paused. However, I am getting an error: Exception in thread "AWT-EventQueue-0" java.lang.IllegalMonitorStateException
2 Threads are started, but I can't stop it with the wait() method. Please let me know how can I stop threads, and implement resume button. Thanks. Easy Example below
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
class FirstCountDown extends SwingWorker<Integer, Integer> {
public Integer doInBackground() {
for(int i=0; i<1000; i++){
CountDown.count1.setText(String.valueOf(1000-i));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
}
class SecondCountDown extends SwingWorker<Integer, Integer> {
public Integer doInBackground(){
for(int i=0; i<1000; i++){
CountDown.count2.setText(String.valueOf(1000-i));
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
}
class CountDown extends JFrame {
static JLabel count1;
static JLabel count2;
static JButton startButton;
static JButton pauseButton;
static JButton resumeButton;
FirstCountDown first = new FirstCountDown();
SecondCountDown second = new SecondCountDown();
public CountDown(){
count1 = new JLabel("1000");
count2 = new JLabel("1000");
startButton = new JButton("start");
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
first.execute();
second.execute();
}
});
pauseButton = new JButton("pause");
pauseButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
try {
first.wait();
second.wait();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
resumeButton = new JButton("resume");
setSize(300,100);
setLayout(new FlowLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(count1);
add(count2);
add(startButton);
add(pauseButton);
add(resumeButton);
setVisible(true);
}
public static void main(String args[]) {
CountDown g = new CountDown();
}
}
You can't suspend a thread execution by invoking wait() on it. wait() suspend the current thread until another thread calls notify() or notifyAll() on the same object the previous thread called wait() on. Moreover, in order to call wait(), notify() or notifyAll() on an object, the calling thread must hold that object's monitor by doing
synchronized(object) {
object.wait();
}
In order to suspend your counting, you need a flag and provide two methods to suspend and resume your counting. Something like:
class FirstCountDown extends SwingWorker<Integer, Integer> {
private _suspended = false;
public synchronized void suspend() { _suspended = true; notify(); }
public synchronized void resume() { _suspended = false; notify(); }
public Integer doInBackground() {
for(int i=0; i<1000; i++) {
synchronized(this) {
while (_suspended) {
wait(); // The current thread will block until some else calls notify()
// Then if _suspended is false, it keeps looping the for
}
}
CountDown.count1.setText(String.valueOf(1000-i));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
}
I need to make a method that returns only when a JButton is pressed. I have a custom JButton class
public class MyButton extends JButton {
public void waitForPress() {
//returns only when user presses this button
}
}
and I want to implement waitForPress. Basically, the method should only return when the user presses the button with their mouse. I have achieved similar behavior for JTextField (to return only when user presses Space):
public void waitForTriggerKey() {
final CountDownLatch latch = new CountDownLatch(1);
KeyEventDispatcher dispatcher = new KeyEventDispatcher() {
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_SPACE) {
System.out.println("presed!");
latch.countDown();
}
return false;
}
};
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(dispatcher);
try {
//current thread waits here until countDown() is called (see a few lines above)
latch.await();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(dispatcher);
}
but I would like to do the same thing with JButton.
In advance: Please, if you wish to comment saying that this is not a good idea and that one should simply wait for actionPerformed event on a JButton and then do some action, please realize I already know that and have a good reason for doing what I'm asking here. Please try to only help with what I've asked. Thanks!!
In advance: Please, also realize that implementing actionPerformed also will not directly solve the problem. Because the code will progress even without the button being pressed. I need the program to stop, and only return when the button has been pressed. Here is a terrible solution if I were to use actionPerformed:
public class MyButton extends JButton implements ActionPerformed {
private boolean keepGoing = true;
public MyButton(String s) {
super(s);
addActionListener(this);
}
public void waitForPress() {
while(keepGoing);
return;
}
public void actionPerformed(ActionEvent e) {
keepGoing = false;
}
}
For what it's worth, here is how you can do it with wait() and notify() but yet I feel that there is a deeper problem here. I would not consider this as a satisfying solution:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class TestBlockingButton {
boolean clicked = false;
private Object toNotify;
private void initUI() {
JFrame frame = new JFrame(TestBlockingButton.class.getSimpleName());
JButton button = new JButton("Click me");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
clicked = true;
if (toNotify != null) {
synchronized (TestBlockingButton.this) {
toNotify.notify();
}
}
}
});
frame.add(button);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void waitForProcess() {
toNotify = this;
while (!clicked) {
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
System.out.println("continuing work");
}
public static void main(String[] args) {
final TestBlockingButton test = new TestBlockingButton();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
test.initUI();
}
});
ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
pool.execute(new Runnable() {
#Override
public void run() {
System.out.println("I was doing something and now I will wait for button click");
test.waitForProcess();
System.out.println("User has now cliked the button and I can continue my work");
}
});
}
}
As you asked for an implementation with a mutex, here's what it would be like.
I'm using an ActionListener though, but there's no busy wait in it. If that isn't what you desire, you atleast saw what Burkhard meant ;)
public class MyButton extends JButton implements ActionListener
{
private Semaphore sem = new Semaphore(1);
public MyButton(String text) throws InterruptedException
{
super(text);
addActionListener(this);
sem.acquire();
}
#Override
public void actionPerformed(ActionEvent e) {
sem.release();
}
public void waitForPress() throws InterruptedException {
sem.acquire();
//do your stuff
sem.acquire();
//or just
//waitForPress()
//if you dont want it to end.
}
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame();
MyButton m = new MyButton("test");
frame.add(m);
frame.pack();
frame.setVisible(true);
m.waitForPress();
//another time, if you only want it to block twice
m.waitForPress();
}
}
But I don't think this is a clean approach, but it doesn't consume CPU-time like a while(isStatementTrue)-implementation.
An important thing here is: you're blocking the main thread with m.waitForPress() but as you wrote you're quite experienced and you know how to handle that.
I'm currently building a Java application using two threads :
The first thread is about the UI of the application, and also the processing of command received via the bluetooth thread.
The bluetooth thread is bluetooth server waiting for a robot to connect and handling communication.
As of now, the UI thread is in wait() state until the bluetooth thread gets a new message to process.
The problem is, I can trace the notify/notifyAll call from the bluetooth thread, but my UI is not resuming it's activity.
I am now sure I misunderstood something about the proper way to manage synchronized threads, but I can't figure out what's wrong in my software.
Here is the code for the UI :
package mapper;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
public class MapperUI extends JFrame implements Runnable {
private ArrayList<String> messageArray;
public MapperUI(){
super();
build();
this.setVisible(true);
new Thread(this).start();
}
private void build(){
setTitle("SLAM Mapper");
setSize(600,500);
setLocationRelativeTo(null);
setResizable(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setContentPane(buildContentPane());
}
private JPanel buildContentPane(){
JPanel main = new JPanel();
main.setLayout(new BorderLayout());
//TODO Implements auto-generated map after bluetooth communication
MapPanel map = new MapPanel();
main.add(map,BorderLayout.CENTER);
//TODO This fields will be buildt with stored message
JTable positions = new JTable(15,2);
main.add(positions,BorderLayout.EAST);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
JButton bouton = new JButton("Start");
buttonPanel.add(bouton);
JButton bouton2 = new JButton("Send");
buttonPanel.add(bouton2);
main.add(buttonPanel,BorderLayout.SOUTH);
return main;
}
public synchronized void run(){
MapperCom bt = new MapperCom();
while(true){
try {
System.out.println("Mapper is Waiting......");
wait();
String message = bt.getMessage();
this.messageArray.add(message);
bt.setNextCommand(processMessage(message));
notifyAll();
System.out.println("Mapper Notify");
build();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public String processMessage(String message){
String command = "";
//TODO Build a response
command = "fffff\n";
return command;
}
}
Here is the bluetoothService :
package mapper;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;
public class MapperCom extends Thread {
public final UUID uuid = new UUID(
"27012f0c68af4fbf8dbe6bbaf7aa432a", false);
public final String name = "Server";
public final String url = "btspp://localhost:" + uuid
+ ";name=" + name
+ ";authenticate=false;encrypt=false;";
private LocalDevice local ;
private StreamConnectionNotifier server ;
private StreamConnection conn ;
private DataInputStream din ;
private DataOutputStream dout ;
private String command;
private String message;
public MapperCom(){
try {
this.command = "";
this.message = "";
System.out.println("Setting device to be discoverable...");
local = LocalDevice.getLocalDevice();
local.setDiscoverable(DiscoveryAgent.GIAC);
System.out.println("Start advertising service...");
server = (StreamConnectionNotifier)Connector.open(url);
System.out.println("Waiting for incoming connection...\n");
conn = server.acceptAndOpen();
System.out.println("Client Connected...");
din = new DataInputStream(conn.openInputStream());
dout = new DataOutputStream(conn.openOutputStream());
new Thread(this).start();
} catch (Exception e) {
System.out.println("Exception Occured: " + e.toString());
}
}
#Override
public synchronized void run(){
System.out.println("Bluetooth Thread Started");
while(true){
try {
String cmd = "";
char c;
System.out.println("Waiting for message");
while (((c = din.readChar()) > 0) && (c!='\n') ){
System.out.println("Char received :"+c);
cmd = cmd + c;
}
storeMessage(cmd);
System.out.println("Bt Notify......");
notifyAll();
System.out.println("Bt is Waiting for a command from mapper......");
wait();
sendResponse();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void sendResponse(){
try {
dout.writeChars(command);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized String getMessage(){
return this.message;
}
public synchronized void storeMessage (String data){
this.message = data;
System.out.println("Received " + data);
}
public synchronized int setNextCommand (String data){
int result = -1;
//TODO Implement proper protocol
this.command = data;
System.out.println("Sending " + data);
return result;
}
}
I think when you call notifyAll(), it calls this.notifyAll(). Which there are no other elements waiting in the same class. So what you can do is you share the same object over both classes and call obj.wait() and obj.notifyAll(). It will work.
Below is one sample program. Basically there needs some common lock between 2 threads if you want communication using wait & notify.
package ravi.tutorial.java.threads;
public class TestThreads {
/**
* #param args
*/
public static void main(String[] args) {
CommonLock commonLock = new CommonLock();
Thread1 thread1 = new Thread1(commonLock);
Thread2 thread2 = new Thread2(commonLock);
thread1.start();
thread2.start();
}
}
/*
* Common monitor lock between both threads, used for communication using wait
* notify.
*/
class CommonLock {
}
// Extending Thread instead of Runnable as its just a test
class Thread1 extends Thread {
private CommonLock commonLock;
public Thread1(CommonLock commonLock) {
this.commonLock = commonLock;
}
public void run() {
System.out.println("Started thread 1");
System.out.println("waiting thread 1");
try {
// TO wait on commonLock, first need to get lock on commonLock. SO
// put synchronized block of commonLock.
synchronized (commonLock) {
commonLock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("DONE waiting thread 1 as I got notification from THread 2");
}
}
class Thread2 extends Thread {
private CommonLock commonLock;
public Thread2(CommonLock commonLock) {
this.commonLock = commonLock;
}
public void run() {
System.out.println("Running thread 2");
try {
System.out.println("Sleeping thread 2");
// Just take gap of 2 sec before notifying.
Thread.sleep(2000);
// TO notify on commonLock, first need to get lock on commonLock. SO
// put synchronized block of commonLock.
synchronized (commonLock) {
System.out.println("Notifying thread 2");
commonLock.notifyAll();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Look at this: Thread tutorial
wait( ) tells the calling thread to give up the monitor and go to
sleep until some other thread enters the same monitor and calls
notify( ).
notify( ) wakes up the first thread that called wait( ) on
the same object.
notifyAll( ) wakes up all the threads that called wait( ) on the
same object. The highest priority thread will run first.
This is main misunderstanding of thread conception in Java.
i use from a class that extended from jframe and it has a button(i use from it in my program)
i want when run jframe in my program the whole of my program pause
until i press the button.
how can i do it
in c++ getch() do this.
i want a function like that.
Pausing Execution with Sleep, although I doubt that is the mechanism that you'll want to use. So, as others have suggested, I believe you'll need to implement wait-notify logic. Here's an extremely contrived example:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
#SuppressWarnings("serial")
public class PanelWithButton extends JPanel
{
// Field members
private AtomicBoolean paused;
private JTextArea textArea;
private JButton button;
private Thread threadObject;
/**
* Constructor
*/
public PanelWithButton()
{
paused = new AtomicBoolean(false);
textArea = new JTextArea(5, 30);
button = new JButton();
initComponents();
}
/**
* Initializes components
*/
public void initComponents()
{
// Construct components
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
add( new JScrollPane(textArea));
button.setPreferredSize(new Dimension(100, 100));
button.setText("Pause");
button.addActionListener(new ButtonListener());
add(button);
// Runnable that continually writes to text area
Runnable runnable = new Runnable()
{
#Override
public void run()
{
while(true)
{
for(int i = 0; i < Integer.MAX_VALUE; i++)
{
if(paused.get())
{
synchronized(threadObject)
{
// Pause
try
{
threadObject.wait();
}
catch (InterruptedException e)
{
}
}
}
// Write to text area
textArea.append(Integer.toString(i) + ", ");
// Sleep
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
}
}
}
}
};
threadObject = new Thread(runnable);
threadObject.start();
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(400, 200);
}
/**
* Button action listener
* #author meherts
*
*/
class ButtonListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent evt)
{
if(!paused.get())
{
button.setText("Start");
paused.set(true);
}
else
{
button.setText("Pause");
paused.set(false);
// Resume
synchronized(threadObject)
{
threadObject.notify();
}
}
}
}
}
And here's your main class:
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class MainClass
{
/**
* Main method of this application
*/
public static void main(final String[] arg)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new PanelWithButton());
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
});
}
}
As you can see, this example application will continually write to the text area until you click the button that reads 'Pause', whereupon to resume you'll need to click that same button which will now read 'Start'.
You don't say what you mean by pause. What is your app doing?
As a rule of thumb you CAN'T pause a UI app. User interface applications run from a message processing loop. Message comes in, message is dispatched, loop waits for another message. An app still needs to handles things like the user clicking on buttons, resizing the window, closing the app and so forth so this loop runs continuously.
If you want your application to "pause" in the sense of prevent the user doing something, just grey out whatever button or menu it is you don't want users to be doing.
If your app is running a thread in the background and wish it to suspend that action until you resume it, you can do so fairly easily like this.
MyThread mythread = new MyThread();
// Main thread
void pause() {
mythread.pause = true;
}
void resume() {
synchronized (mythread) {
mythread.pause = false;
mythread.notify();
}
}
class MyThread extends Thread {
public boolean pause = false;
public void run() {
while (someCondition) {
synchronized (this) {
if (pause) {
wait();
}
}
doSomething();
}
}
}
It is also possible to use Thread.suspend(), Thread.resume() to accomplish similar but these are inherently dangerous because you have no idea where the thread is when you suspend it. It could have a file open, be half way through sending a message over a socket etc. Putting a test in whatever loop controls your thread allows you do suspend at a point when it is safe to do so.
This answer entirely depends on whether I understand your question correctly, please give a bit more info if you want better answers. Here goes:
Pausing in a loop scenario
boolean paused;
while(true ) {
if(paused)
{
Thread.sleep(1000); // or do whatever you want in the paused state
} else {
doTask1
doTask2
doTask3
}
}
Threads:
You can also put those tasks into a seperate thread and not on the GUI thread which is typically what you would do for long running operations.
Pausing a thread is very easy. Just call suspend() on it. When you want to unpause call resume(). These methods however are dangerous and have been deprecated. Better or rather safer way to do it would be similar to the above by checking a pause flag.Here is a short example I had lying around in my snippets. Cant exactly remember where I got it in the first place:
// Create and start the thread
MyThread thread = new MyThread();
thread.start();
while (true) {
// Do work
// Pause the thread
synchronized (thread) {
thread.pleaseWait = true;
}
// Do work
// Resume the thread
synchronized (thread) {
thread.pleaseWait = false;
thread.notify();
}
// Do work
}
class MyThread extends Thread {
boolean pleaseWait = false;
// This method is called when the thread runs
public void run() {
while (true) {
// Do work
// Check if should wait
synchronized (this) {
while (pleaseWait) {
try {
wait();
} catch (Exception e) {
}
}
}
// Do work
}
}
} // Create and start the thread
MyThread thread = new MyThread();
thread.start();
while (true) {
// Do work
// Pause the thread
synchronized (thread) {
thread.pleaseWait = true;
}
// Do work
// Resume the thread
synchronized (thread) {
thread.pleaseWait = false;
thread.notify();
}
// Do work
}
class MyThread extends Thread {
boolean pleaseWait = false;
// This method is called when the thread runs
public void run() {
while (true) {
// Do work
// Check if should wait
synchronized (this) {
while (pleaseWait) {
try {
wait();
} catch (Exception e) {
}
}
}
// Do work
}
}
}
Hope this helps
try my java pause button:
package drawFramePackage;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Milliseconds2 implements ActionListener, MouseListener{
JFrame j;
Timer t;
Integer onesAndZeros, time, time2, placeHolder2;
Boolean hasFired;
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new Milliseconds2();
}
public Milliseconds2(){
j = new JFrame();
j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
j.setSize(new Dimension(300, 300));
j.setVisible(true);
j.addMouseListener(this);
onesAndZeros = new Integer(0);
time = new Integer(0);
time2 = new Integer(0);
placeHolder2 = new Integer(0);
hasFired = new Boolean(true);
t = new Timer(2400, this);
time = (int) System.currentTimeMillis();
t.start();
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
if (onesAndZeros.equals(0)){
t.stop();
if (hasFired){
time2 = t.getDelay() - ((int) System.currentTimeMillis() - time);
}
else{
time2 -= (int) System.currentTimeMillis() - placeHolder2;
}
if (hasFired){
hasFired = false;
}
onesAndZeros = -1;
}
if (onesAndZeros.equals(1)){
//System.out.println(time2);
t.setInitialDelay(time2);
t.start();
placeHolder2 = (int) System.currentTimeMillis();
onesAndZeros = 0;
}
if (onesAndZeros.equals(-1)){
onesAndZeros = 1;
}
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
time = (int) System.currentTimeMillis();
hasFired = true;
System.out.println("Message");
}
}
Freezing your Main Thread will effectively freeze the entire program and could cause the operating system to think the application has crashed, not quite sure so correct me if I'm wrong. You could try to hide/disable the controls and enable them again when the user clicks on your button.
UI performs task using message driven mechanism.
If you have a button in your UI and you want to run something when that button is pressed, you should add an object of ActionListener to your button. Once the button is pressed, it fires the ActionListener object to perform a task, e.g.:
button.addActionListener(new ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// do something
}
});
If you want to stop something when you press a pause button, you will defnitely need a Thread. This is more complicated than the former case.