I have a program that estimates the value of PI every million trials. However, I want the program to be paused when I click on pause and to resumes when I click on run, using wait() and notify().
I must use multiple threads as well as a Boolean as a signal of where should it pause and run, but I do not know how. I am confused.
Any ideas?
package com.company;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Ex03 extends JFrame implements Runnable, ActionListener {
int n = 0;
int c = 0;
double Pi;
int change = 1000000;
boolean runing = true;
JLabel actualpi = new JLabel("The Actual value of PI " + Math.PI);
JLabel estimation = new JLabel("Current Estimate: ");
JLabel tri = new JLabel("Number Of Trials: " + n);
JButton run = new JButton("Run");
JButton pause = new JButton("Pause");
public Ex03() {
super("Ex 03");
setLayout(new GridLayout(4, 1));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
setVisible(true);
add(actualpi);
add(estimation);
add(tri);
add(run);
run.addActionListener(this);
pause.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
Thread thread = new Thread(this);
if (e.getSource() == run) {
thread.start();
remove(run);
add(pause);
} else if (e.getSource() == pause) {
remove(pause);
add(run);
try {
thread.wait();
} catch (InterruptedException e1) {
}
}
}
public void run() {
n++;
while (runing) {
double x = Math.random();
double y = Math.random();
if (((x * x) + (y * y)) <= 1)
c++;
n++;
Pi = (4.0 * (double) c / n);
if (n == change) {
estimation.setText("Current Estimate: " + Pi);
tri.setText("Number Of Trials: " + n);
change = change + 1000000;
}
try {
Thread.sleep(0);
} catch (InterruptedException e) {
}
}
}
public static void main(String[] args) {
new Ex03();
}
}
Here is example how to do it in console application using Semaphore:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
public class Main {
public static void main(String[] args) throws Exception {
PiThread piThread = new PiThread();
piThread.start();
BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
String cmd;
while ((cmd = bufferRead.readLine()) != null) {
System.out.println("write p to pause, r to resume, s to stop");
switch (cmd) {
case "p":
piThread.pauseComputation();
break;
case "r":
piThread.resumeComputation();
break;
case "s":
piThread.stopComputation();
piThread.join();
return;
}
}
}
public static class PiThread extends Thread {
private volatile boolean stop = false;
private volatile int total = 0;
private volatile int insideCircle = 0;
private Semaphore semaphore = new Semaphore(1, true);
#Override
public void run() {
while (!stop) {
for (int i = 0; i < 1000; i++) {
double x = Math.random();
double y = Math.random();
if (((x * x) + (y * y)) <= 1)
insideCircle++;
total++;
}
// using semaphores is slow
try {
// not to garbage stdout
Thread.sleep(100);
semaphore.acquire();
semaphore.release();
}
catch (InterruptedException e) {
// exit
return;
}
System.out.println("pi: " + getPiApproximation());
System.out.flush();
}
}
public void pauseComputation() {
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void resumeComputation() {
semaphore.release();
}
public void stopComputation() {
stop = true;
}
public double getPiApproximation() {
return 4*(double)insideCircle / (double)total;
}
}
}
It may not be the best way to handle this in GUI but will give you a good start. The main idea is to use Semaphore to block worker thread. For this to work you must always call pauseComputation before resumeComputation otherwise there will be deadlock. After you call stopComputation you cannot resumeComputation or pauseComputation.
Related
I have to make a DieTester for school. One that rolls the dice 100 times and then puts the output in a Table Chart and another table.
The problem is that my Thread wont sleep with the time that is set by the Slider.
Here my DieTester:
package sample.Controllers;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.RunnableFuture;
public class DieTester implements Runnable{
private Thread t;
private String Threadname;
List<Integer> List = new ArrayList();
Random rand = new Random();
long l;
public DieTester(String name){
Threadname = name;
}
public void run() {
for (int n = 0; n < 100; n++) {
try {
Thread.sleep(getTime());
List.add(rand.nextInt(6) + 1);
System.out.println(List.get(n));
} catch (InterruptedException e) {
System.out.println("Error");
}
}
}
public void start(){
if (t == null)
{
t = new Thread (this, Threadname);
t.start ();
}
}
public void setTime(double SliderTime){
l = (long) SliderTime;
}
public long getTime(){
return l;
}
}
Here the controller:
package sample.Controllers;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Slider;
public class Controller {
DieTester dice = new DieTester("Time");
double time=0;
EventHandler e = new EventHandler() {
#Override
public void handle(Event event) {
time = TimeSlider.getValue();
}
};
#FXML
Slider TimeSlider = new Slider(50, 2000, 50);
#FXML
public void HandlePauseResumeAction(){
}
#FXML
public void HandleStartAction(){
DieTester die = new DieTester("Start");
die.start();
}
#FXML
public void HandleSlider(){
TimeSlider.valueProperty().addListener((observable, oldValue, newValue) -> {
time = TimeSlider.getValue() * 20;
//System.out.println(time);
dice.setTime(time);
});
System.out.println(dice.getTime());
}
}
The slider and everything is set up properly. And if I call the getTime() it puts out the time properly, but the Thread isn't sleeping or something.
This is a mutable shared variable :
long l
Threads access it concurrently, (one reads, one writes), yet it doesn't have proper synchronization, so writes of one thread are not guaranteed to be seen by the other thread.
On top of that, l is initialized to 0, and odds are the spawned thread has raced through 100 loops, without really sleeping, before the first property change event happens.
Ok guys so I figured it out, this is what I did
#FXML
public void HandleStartAction(){
start();
}
public void run(){
for(int n = 0; n < 100; n++){
try {
if(!suspend){
Thread.sleep((long)TimeSlider.getValue() * 20);
List.add(rand.nextInt(6) + 1);
System.out.println(List.get(n));
}else{
}
} catch (InterruptedException e) {
System.out.println("Error");
}
}
}
public void start(){
if (t == null)
{
t = new Thread (this, "Start");
t.start ();
}
}
I am trying execute two jobs simultaneously. One of the things that I am trying to do is displaying a count up timer and the other one is moving the ball.
This is where I create the timer and also call the moveBall method
button.addChangeListener(new ChangeListener() {
int start = 0;
public void stateChanged(ChangeEvent e) {
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
timeValue.setText(++start + " sec");
}
};
timer = new Timer(1000, taskPerformer);
timer.start();
ball.moveBall();
}
});
This is my moveBall method
public void moveBall() {
Thread ball = new Thread() {
double counter = 0;
int t = (int) (2 * Vy / 9.8);
public void run() {
try {
while (t >= 0) {
// calculate Vx and Vy
Ball.this.setX(Ball.this.getX() + Vx);
Ball.this.setY(Ball.this.getY() - Vy);
counter += 50;
if (counter == 1000) {
t--;
counter = 0;
}
paintingComponent.repaint();
Thread.sleep(20);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
ball.start();
}
When I execute the above code the label for displaying the time passed is not changing at all during the ball is moving and when the movement is over it takes the last number that it supposed to take.
This is a example two executions of two threads, Java simultaneous execution
public class ThreadExecutor extends Thread {
private String name;
private int executionCount;
public ThreadExecutor(final String name, final int executionCount) {
this.name = name;
this.executionCount = executionCount;
}
#Override
public void run() {
int count = 1;
while (count <= executionCount) {
System.out.println("Executing thread ".concat(name).concat(" : ") + count);
count++;
}
}
}
public class Main {
public static void main(String args[]) {
final ThreadExecutor one = new ThreadExecutor("One", 1);
final ThreadExecutor two = new ThreadExecutor("Two", 2);
one.start();
two.start();
}
}
I'm trying to make a program that generates random numbers if the user presses a button. It should stop generating them, when the user presses the button the second time, and then it should print all the random numbers added together and the average random number, but I don't know how I should do this. When I'm in the loop i can't press the button. I'll be thankful for any help. My Code:
package Test;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Average
{
static int sizeX = 200;
static int sizeY = 200;
static int maxNum = 100;
static int minNum = 1;
static boolean running = true;
static JButton b1 = new JButton("Click me");
static void JFrame()
{
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension dim = tk.getScreenSize();
JFrame f = new JFrame("Test");
f.setSize(sizeX, sizeY);
f.setVisible(true);
f.setLocation((dim.width - sizeX) / 2, (dim.height - sizeY) / 2);
f.setResizable(false);
f.setAutoRequestFocus(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(b1);
}
static void ActionListener()
{
b1.addActionListener(new ActionListener()//ActionListener
{
public void actionPerformed(ActionEvent e)//Execute when button is pressed
{
int numsGenerated = 0;
double ave = 0;
if (running == true)
{
while (true)
{
double r = Math.random() * (maxNum - minNum) + minNum; //(maxNum - minNum) + minNum
numsGenerated++;
ave = ave + r;
System.out.println("Random: " + r);
if (!running)
{
break;
}
}
running = false;
}
else
{
System.out.println("");
System.out.println("All: " + ave);
System.out.println("Average: " + ave / numsGenerated);
running = true;
}
}
}); //ActionListenerEnd
}
public static void main(String[] args)//Main
{
JFrame();
ActionListener();
}
}
As Ordous told in a comment, you should make a different thread for this work. But you may need to synchronize on "running" variable to make sure it works always.
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Average
{
static Object lock=new Object();
static int sizeX = 200;
static int sizeY = 200;
static int maxNum = 100;
static int minNum = 1;
static boolean running = false;
static JButton b1 = new JButton("Click me");
static void JFrame()
{
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension dim = tk.getScreenSize();
JFrame f = new JFrame("Test");
f.setSize(sizeX, sizeY);
f.setVisible(true);
f.setLocation((dim.width - sizeX) / 2, (dim.height - sizeY) / 2);
f.setResizable(false);
f.setAutoRequestFocus(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(b1);
}
public class Thr extends Thread
{
#Override
public void run()
{
int numsGenerated = 0;
double ave = 0;
synchronized(lock)
{
running=!running;
}
if (running == true)
{
while (true)
{
double r = Math.random() * (maxNum - minNum) + minNum; //(maxNum - minNum) + minNum
numsGenerated++;
ave = ave + r;
System.out.println("Random: " + r);
synchronized(lock)
{
if (!running)
{
break;
}
}
}
synchronized(lock)
{
running = false;
}
}
System.out.println("");
System.out.println("All: " + ave);
System.out.println("Average: " + ave / numsGenerated);
running = true;
}
}
static Thr thread=null;
static void ActionListener()
{
b1.addActionListener(new ActionListener()//ActionListener
{
public void actionPerformed(ActionEvent e)//Execute when button is pressed
{
Average av=new Average();
if(thread==null)
{
thread=av.new Thr(); // should add in an executor
thread.start();
}
else
{
synchronized(lock)
{
running=false;
}
}
}
}); //ActionListenerEnd
}
public static void main(String[] args)//Main
{
JFrame();
ActionListener();
}
}
To have a simple thread, "Thread" is inherited and run() methoud must be overridden to use it. (you can use a "Runnable" instead of this too)
public class Thr extends Thread
{
#Override
public void run()
{
}
}
You start it like
threadName.Start()
or
ExecutorObject.submit(threadName);
where executor object has a pool for threads to run efficiently and is created by executor service.
Do not start threads with
threadname.run()
directly.
Also inter-thread communication is important. One thread leaves a message to somewhere, another thread reads. If there is no synchronization, they can race for the variable's visibility and wrong output can happen.
You can have an object to lock on.
synchronized(lock)
{
}
so this block can be entered by only single thread until it exits from this block. You should leave a message for other threads, to say "its ready" and wake them up(iff they are waiting) with
synchronized(lock)
{
lock.notifyAll();
}
then make the message-leaving thread (current thread) go on a waiting state so other threads can wake it up and let it exit the block.
synchronized(lock)
{
lock.notifyAll();
lock.wait();
}
but this alone is not enough because current thread accidentally exit the waiting state so you may force it to keep waiting:
synchronized(lock)
{
lock.notifyAll();
while(condition)
lock.wait();
}
if you make sure only a single thread can access a variable at a time, you can use it to communicate with other threads.
You can use some other ways to have barriers to synchronize all threads on a point so no threads can continue until all hit the same barrier. More communication can decrease overall performance.
Main program is a thread too, so it can wait, notify and synchronize.
There is a problem, the following code does not work
code:
Server
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
static ServerSocket serverSocket;
static Socket socket;
static DataOutputStream out;
static DataInputStream in;
static Users[] user = new Users[10];
public static void main(String[] args) {
try {
System.out.println("Server Started...");
serverSocket = new ServerSocket(7778);
System.out.println("Server Start.");
while (true) {
socket = serverSocket.accept();
for (int i = 0; i < 10; i++) {
if (user[i] == null) {
System.out.println("Conection from"
+ socket.getInetAddress());
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
user[i] = new Users(out, in, user, i);
Thread thread = new Thread(user[i]);
thread.start();
break;
}
}
}
} catch (IOException e) {
}
}
}
class Users implements Runnable {
DataOutputStream out;
DataInputStream in;
Users[] user = new Users[10];
String name;
int playerid;
int playeridln;
int xin;
int yin;
public Users(DataOutputStream out, DataInputStream in, Users[] user, int pid) {
this.out = out;
this.in = in;
this.user = user;
this.playerid = pid;
}
public void run() {
try {
out.writeInt(playerid);
} catch (IOException e1) {
System.out.println("Failed to send PlayerID");
}
while (true) {
try {
playeridln = in.readInt();
xin = in.readInt();
yin = in.readInt();
for (int i = 0; i < 10; i++) {
if (user[i] != null) {
user[i].out.writeInt(playeridln);
user[i].out.writeInt(xin);
user[i].out.writeInt(yin);
}
}
} catch (IOException e) {
user[playerid] = null;
break;
}
}
}
}
Client
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Client extends JPanel implements Runnable, KeyListener {
private static final long serialVersionUID = 1L;
static Socket socket;
static DataInputStream in;
static DataOutputStream out;
int playerid;
int[] x = new int[10];
int[] y = new int[10];
boolean left, up, right, down;
int playerx;
int playery;
public Client() {
init();
}
public void init() {
try {
System.out.println("Conecting to serever...");
socket = new Socket("localhost", 7778);
System.out.println("Connection successful");
in = new DataInputStream(socket.getInputStream());
playerid = in.readInt();
out = new DataOutputStream(socket.getOutputStream());
Input input = new Input(in, this);
Thread thread = new Thread(input);
thread.start();
Thread thread2 = new Thread(this);
thread2.start();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void updateCoordinates(int pid, int x2, int y2) {
this.x[pid] = x2;
this.y[pid] = y2;
}
public void paint(Graphics g) {
repaint();
for (int i = 0; i < 10; i++) {
g.drawOval(x[i], y[i], 5, 5);
}
}
public void run() {
while (true) {
if (right) {
playerx += 10;
}
if (left) {
playerx -= 10;
}
if (down) {
playery += 10;
}
if (up) {
playery -= 10;
}
if (right || left || up || down) {
try {
out.writeInt(playerid);
out.writeInt(playerx);
out.writeInt(playery);
} catch (Exception e) {
System.out.println("Erro Coordinates");
}
}
repaint();
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 37) {
left = true;
}
if (e.getKeyCode() == 38) {
up = true;
}
if (e.getKeyCode() == 39) {
right = true;
}
if (e.getKeyCode() == 40) {
down = true;
}
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == 37) {
left = false;
}
if (e.getKeyCode() == 38) {
up = false;
}
if (e.getKeyCode() == 39) {
right = false;
}
if (e.getKeyCode() == 40) {
down = false;
}
}
public void keyTyped(KeyEvent e) {
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setSize(300, 300);
f.getContentPane().add(new Client());
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class Input implements Runnable {
DataInputStream in;
Client client;
public Input(DataInputStream in, Client c) {
this.in = in;
this.client = c;
}
public void run() {
while (true) {
try {
int playerd = in.readInt();
int x = in.readInt();
int y = in.readInt();
client.updateCoordinates(playerd, x, y);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
When I run the code (run multiple windows to check) It does not work, even though the circle should move ..
Help to solve it, please)
Thank you in advance!
This is rather complicated stuff. There's two problems I can see.
Minor problem (I think): Swing classes and methods, with very few exceptions (such as the repaint() method in Component/JComponent) must run on the event queue. In your Client the main() method, which runs on the startup thread, creates a JFrame and calls several methods. Everybody does this, and I think everybody gets away with it, but it's dangerous. Use EventQueue.InvokeLater to put the code onto the UI thread. I checked your run() methods, but they don't seem to touch Swing, (other than a legit call to repaint()) but keep an eye on them. Call a Swing method from there and you'll have a bigger problem.
Major problem: You have a bunch of fields referenced in the Client run method and in some button code (running on the UI thread). (playerx, playery, left, right, up, down) Synchronization is not really a problem here. However, the JVM is under no obligation (though it can if it wants) to inform a thread of changes made by other threads. Having done this myself, I've found that sometimes the threads see changes immediately, sometimes after a noticable lag (leading to annoying, jumpy graphics), and sometimes never.
The language spec requires that data be transferred between threads when a thread starts, when it finishes with a join, when a thread enters a synch block after another thread has left a block synched on the same object, when a volatile field is written and read, and after calls to Atomic methods.
So what you want to do is go through, manually, all the fields in your Client class and for each one make sure it is marked as final, volatile, or referenced only in synchronized blocks or only referenced on one thread (like Swing methods). The quickest thing for you to do would be make those fields volatile. Synch blocks might be more efficient. I believe that they cost more to get into and out of than reads and writes to volatiles, but once in you can modify a bunch of fields at little extra cost.
I've got thread class which increments lable value from 0 to n. Thread code:
public class
SimpleThread implements Runnable {
Thread t;
volatile boolean stop = true;
int n;
JLabel label;
String name;
SimpleThread(String name) {
this.name = name;
t = new Thread(this, "settingThread");
t.start();
}
public void run() {
while (true) {
while (stop) {
}
System.out.println(name + " stop:" + stop);
for (int i = 0; i < n; i++) {
label.setText(String.valueOf(i));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
stop = true;
}
}
public void start(int n, JLabel label) {
stop = false;
this.n = n;
this.label = label;
}
}
Thread must work until stop value isn't true. Also I've got 2 thread objects st1 and st2 with different arguments:
st1.start(10, timeLabel1);
st2.start(5, timeLabel2);
So first thread should increment timeLabel1 from 0 to 10 and st2 - from 0 to 5. And now the question. How can I make my programm wait until threads has passed the stage in the cycle? I mean something like this:
public void run() {
while (true) {
while (stop) {
}
System.out.println(name + " stop:" + stop);
for (int i = 0; i < n; i++) {
label.setText(String.valueOf(i));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
stop = true;
//stage
}
}
And then:
st1.start(10, timeLabel1);
st2.start(5, timeLabel2);
//wait until both stages aren't done
System.out.println("yep");
Code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Created with IntelliJ IDEA.
* User: Администратор
* Date: 22.11.13
* Time: 21:17
* To change this template use File | Settings | File Templates.
*/
public class StackOverflow implements ActionListener {
JButton button = new JButton("Button");
SimpleThread st1 = new SimpleThread("1st"), st2 = new SimpleThread("2nd");
JLabel timeLabel1 = new JLabel("0"), timeLabel2 = new JLabel("0");
StackOverflow() {
JFrame jfrm = new JFrame("Strategy fighting");
jfrm.setLayout(new FlowLayout());
jfrm.setSize(300, 150);
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button.addActionListener(this);
jfrm.add(button);
jfrm.add(timeLabel1);
jfrm.add(timeLabel2);
jfrm.setVisible(true);
}
public class SimpleThread implements Runnable {
Thread t;
volatile boolean stop = true;
int n;
JLabel label;
String name;
SimpleThread(String name) {
this.name = name;
t = new Thread(this, "settingThread");
t.start();
}
public void run() {
while (true) {
while (stop) {
}
System.out.println(name + " stop:" + stop);
for (int i = 0; i < n; i++) {
label.setText(String.valueOf(i));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
stop = true;
}
}
public void start(int n, JLabel label) {
stop = false;
this.n = n;
this.label = label;
}
}
public void actionPerformed(ActionEvent e) {
st1.start(10, timeLabel1);
st2.start(5, timeLabel2);
System.out.println("yep");
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new StackOverflow();
}
});
}
}
Your question already has the answer: the Phaser class. ;)
Something like this should do the trick:
static final Phaser phaser = new Phaser(NUM_THREADS + 1); // +1 for the main thread
In your threads:
run() {
// do stage 1
phaser.arriveAndAwaitAdvance(); // wait until everyone is done with stage 1
// do stage 2
}
And in your main:
startThreads(NUM_THREADS);
phaser.arriveAndAwaitAdvance(); // wait until stage 1 is done
// ... do something else