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;
}
}
Related
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.
I'm trying to use threads to show a progress bar on the CLI in java while doing a long operation (generating md5sums for a batch of large files).
I've written a bit of code, and it works, but I'd like to know if I'm using threads correctly as I'm pretty new to this.
I have two class files, ProgressThreadTest.java and CountToABillion.java
CountToABillion.java:
public class CountToABillion implements Runnable {
double count = 0;
public void echoCount() {
System.out.println(count);
}
#Override
public void run() {
for (double x=0;x<1000000000;x++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
echoCount();
}
}
}
ProgressThreadTest.java:
public class ProgressThreadTest {
public static void main(String[] args) throws InterruptedException {
Thread doCount=new Thread(new CountToABillion());
doCount.start();
}
}
It works as expected and counts upwards on the command line.
Anyone have any comments on whether or not this is a good way to do threads?
Also, because I am updating the progress in the counting loop, it will update every 10ms. How would I change the code to only output the count once every second?
Using javax.swing.Timer is probably the easier solution:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class CountToABillion implements Runnable {
double count = 0;
Timer progressTimer;
public void echoCount() {
System.out.println(count);
}
#Override
public void run() {
progressTimer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
echoCount();
}
});
progressTimer.setRepeats(true);
progressTimer.start();
for (double x=0;x<1000000000;x++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
}
progressTimer.stop();
}
}
Using java.util.concurrent.ScheduledThreadPoolExecutor is the better and more scalable solution:
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class CountToABillion implements Runnable {
double count = 0;
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
public void echoCount() {
System.out.println(count);
}
#Override
public void run() {
Runnable task = new Runnable() {
public void run() {
echoCount();
}
};
exec.scheduleAtFixedRate(task, 1, 1, TimeUnit.SECONDS);
for (double x=0;x<1000000000;x++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
}
exec.shutdownNow();
}
}
Option 1:
int sleep = 10; //ms
int echo = 1000; //ms
for (double x=0;x<1000000000;x++) {
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
if((x*sleep % echo) == 0) {
echoCount();
}
}
Option 2:
Create a new Class to manage your counter, it should be able to add, reset and so on. You will have to make sure it's thread safe (writing new values in case you want to update from various threads).
Make one thread that increases the counter in given intervals
Make another thread that polls the current count in other given intervals and print.
long last=0;
#Override
public void run() {
for (double x=0;x<1000000000;x++) {
try {
doWork();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
if((System.currentTimeMillis()-last)>=1000) //post every second
{
last=System.currentTimeMillis();
echoCount();
}
}
}
This will print the count once every second assuming "work" does not take more than a second.
#Override
public void run() {
for (int i = 0; i < 1000000000; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
count = i;
if(i % 100 == 0) {
echoCount();
}
}
}
By using i % 100 == 0 you're checking if i is divisible by 100 without rest value. If that's the case, it means that you have ran 100 times 10ms which is 1000ms which is 1s. So you will output your echoCountt() every second.
This is an okay way to use threads. But your thread will keep running until it has counted to 10000000 seconds.
On a sidenote, you should use 'i' instead of 'x' in for loops. It's more widely used like this and will be easier to read for experienced java developers
I am trying to print odd and even numbers using 2 different threads alternately. I was able to achieve it using wait, notify and synchronize block but now i want to evaluate if we can achieve it without using wait, notify and synchronize.
Following is the code i have but its not working:
public class OddEvenUsingAtomic {
AtomicInteger nm = new AtomicInteger(0);
AtomicBoolean chk = new AtomicBoolean(true);
public static void main(String args[]) {
final OddEvenUsingAtomic pc = new OddEvenUsingAtomic();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (pc.chk.compareAndSet(true, false)) {
System.out.println("Odd: " + pc.nm.incrementAndGet());
}
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {
if (pc.chk.compareAndSet(false, true)) {
System.out.println("Even: " + pc.nm.incrementAndGet());
}
}
}
}).start();
}
}
Any ideas?
I created another version after suggestions from Bruno which seems to be working better:
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class OddEvenUsingAtomic {
AtomicInteger nm = new AtomicInteger(0);
AtomicBoolean chk = new AtomicBoolean(true);
public static void main(String args[]) {
final OddEvenUsingAtomic pc = new OddEvenUsingAtomic();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (pc.chk.get() == Boolean.TRUE) {
System.out.println("Odd: " + pc.nm.incrementAndGet());
pc.chk.compareAndSet(true, false);
}
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {
if (pc.chk.get() == Boolean.FALSE) {
System.out.println("Even: " + pc.nm.incrementAndGet());
pc.chk.compareAndSet(false, true);
}
}
}
}).start();
}
}
The code is not correctly synchronized, that's the problem.
The following execution order is allowed in your code:
First thread sees chk == true, sets it to false and enters the if block.
Second thread sees chk == false, sets it to true and enters the if block.
Now, you have 2 threads both inside their if blocks, getting ready to:
incrementAndGet() the number
Print it.
Therefore, you have absolutely no control on what is going to happen.
You can have any of the threads call incrementAndGet(), therefore you can have thread "Odd" printing, first, an odd number, and later, an even number.
You can have the first thread print the number, loop, see that the condition is satisfied again (since the second thread has set chk to true again, print, all of this before the second thread had the chance to print).
As you can see, to achieve the result you want, you must have the following operations done atomically:
compareAndSet() the boolean
incrementAndGet() the number
print it
If the 3 operations are not atomic, then you can have the threads being scheduled to run the operations in any possible order, you have no control on the output. The easiest way to achieve this is to use a synchronized block:
public static void main(final String... args) {
final Object o = new Object();
// ... thread 1 ...
synchronized(o) {
if (boolean is in the expected state) { change boolean, get number, increment, print }
}
// ... thread 2 ...
synchronized(o) {
if (boolean is in the expected state) { change boolean, get number, increment, print }
}
}
Here are two threads printing odds and evens with no wait, notify, or synchronized (at least not in the code you can see):
import java.util.concurrent.*;
public class ThreadSignaling {
public static void main(String[] args) {
BlockingQueue<Integer> evens = new LinkedBlockingQueue<>();
BlockingQueue<Integer> odds = new LinkedBlockingQueue<>();
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(() -> takeAndOfferNext(evens, odds));
executorService.submit(() -> takeAndOfferNext(odds, evens));
evens.offer(0);
}
private static void takeAndOfferNext(BlockingQueue<Integer> takeFrom,
BlockingQueue<Integer> offerTo) {
while (true) {
try {
int i = takeFrom.take();
System.out.println(i);
offerTo.offer(i + 1);
} catch (InterruptedException e) {
throw new IllegalStateException("Unexpected interrupt", e);
}
}
}
}
class MultiThreading {
Integer counter = 0;
Thread even;
Thread odd;
boolean flagEven = true;
boolean flagOdd;
class ThreadEven implements Runnable {
#Override
public void run() {
try {
while (counter < 100) {
if (flagEven) {
System.out.println(counter);
counter++;
flagEven = false;
flagOdd = true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class ThreadOdd implements Runnable {
#Override
public void run() {
try {
synchronized (even) {
while (counter < 100) {
if (flagOdd) {
System.out.println(counter);
counter++;
flagOdd = false;
flagEven = true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void start() {
even = new Thread(new ThreadEven());
odd = new Thread(new ThreadOdd());
even.start();
odd.start();
}
}
}
call in the main method
new MultiThreading().start();
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.