There is something wrong with my code. The timer overall seems to be working fine and the pause button does its job.
The problem is when you pause the clock at a specific time and then you unpause it.
If we (let's say) pause it at 8 seconds and we unpause it after a minute, it doesn't keep going like 9-10-11, etc. It goes 74-75-76... (I've broken it into minutes and seconds).
Is it a thread that causes the problem? (Also, I've overused freeze_sec and freeze_min time code snippets just to see if it would be fixed but it wasn't.)
Here is the code:
Thread t1 = null;
ss = new ServerSocket(6800);
while(true) {
s = ss.accept();
isr = new InputStreamReader(s.getInputStream());
br = new BufferedReader(isr);
message = br.readLine();
if (message.equals("START")) {
t1 = new Thread(new Thread1());
t1.start();
...
} else if (message.equals("PAUSE")) {
if(check) {
try {
check = false;
Thread1.PAUSE(true);
} catch (Exception e) {
System.out.println("Exception e");
}
} else {
check = true;
Thread1.PAUSE(false);
}
}
And Thread1 class looks like:
import java.io.*;
import java.util.Date;
import java.util.Scanner;
public class Thread1 extends MyServerFrame implements Runnable{
private static int current_min_time = 0;
private static int current_sec_time = 0;
private static int freeze_min_time = 0;
private static int freeze_sec_time = 0;
private static boolean pause = false;
private static int minutes = 0;
private int total_time_sec = 0;
private static boolean freeze_signal = false;
private static int k = 0;
#Override
public void run() {
long elapsedTime = 0L;
boolean bool = true;
int num = 0;
while (bool) {
Scanner scan = new Scanner(System.in);
if (minutes == 0) {
System.out.println("How many minutes for this half-time?");
Scanner in = new Scanner(System.in);
num = in.nextInt();
minutes = num;
}
long startTime = System.currentTimeMillis();
while (total_time_sec < minutes * 60 || freeze_signal == false) {
if (freeze_signal && k == 0) {
freeze_sec_time = current_sec_time;
freeze_min_time = current_min_time;
k++;
}
if (!pause) {
//perform db poll/check
if (elapsedTime / 1000 != current_sec_time) {
try {
clearTheFile("Half_Time.txt");
} catch (IOException e) {
System.out.println("Exception");
}
if (!freeze_signal && k > 0) {
current_sec_time = freeze_sec_time;
current_min_time = freeze_min_time;
k = 0;
}
current_sec_time++;
total_time_sec = current_sec_time + current_min_time / 60;
print_in_txt();
}
elapsedTime = (new Date()).getTime() - startTime;
if (current_sec_time == 60) {
if (!freeze_signal && k > 0) {
current_sec_time = freeze_sec_time;
current_min_time = freeze_min_time;
try {
clearTheFile("Half_Time.txt");
} catch (IOException e) {
System.out.println("Exception");
}
print_in_txt();
k = 0;
}
current_sec_time = 0;
current_min_time++;
total_time_sec = current_sec_time + current_min_time / 60;
startTime = System.currentTimeMillis();
elapsedTime = (new Date()).getTime() - startTime;
try {
clearTheFile("Half_Time.txt");
} catch (IOException e) {
System.out.println("Exception");
}
print_in_txt();
}
}
}
}
}
public static void clearTheFile(String txt_name) throws IOException {
try {
FileWriter fwOb = new FileWriter(txt_name, false);
PrintWriter pwOb = new PrintWriter(fwOb, false);
pwOb.flush();
pwOb.close();
fwOb.close();
} catch (IOException e) {}
}
public static void print_in_txt() {
PrintWriter out;
try {
out = new PrintWriter("Half_Time.txt");
out.println(String.format("%02d", current_min_time) + ":" + String.format("%02d", current_sec_time));
out.print("");
out.close();
} catch (FileNotFoundException e) {
System.err.println("File doesn't exist");
e.printStackTrace();
}
}
public static void PAUSE(boolean p) {
if (p) {
pause = true;
freeze_signal = true;
} else {
current_sec_time = freeze_sec_time;
current_min_time = freeze_min_time;
try {
clearTheFile("Half_Time.txt");
} catch (IOException e) {
System.out.println("Exception");
}
print_in_txt();
pause = false;
freeze_signal = false;
}
}
}
So, after spending some time bagging my head against the idea, I suddenly realised that you don't actually need the thread at all.
What you need is a way to calculate the duration between to points in time, which doesn't need a thread to update the state, it's done automatically.
The thread is just doing "other stuff"
So, based on that, I took a StopWatch class from one of my previous answers...
public class StopWatch {
private Instant startTime;
private Duration totalRunTime = Duration.ZERO;
public StopWatch start() {
startTime = Instant.now();
return this;
}
public StopWatch stop() {
Duration runTime = Duration.between(startTime, Instant.now());
totalRunTime = totalRunTime.plus(runTime);
startTime = null;
return this;
}
public StopWatch pause() {
return stop();
}
public StopWatch resume() {
return start();
}
public StopWatch reset() {
stop();
totalRunTime = Duration.ZERO;
return this;
}
public boolean isRunning() {
return startTime != null;
}
public Duration getDuration() {
Duration currentDuration = Duration.ZERO;
currentDuration = currentDuration.plus(totalRunTime);
if (isRunning()) {
Duration runTime = Duration.between(startTime, Instant.now());
currentDuration = currentDuration.plus(runTime);
}
return currentDuration;
}
}
And applied so it could be used within a Thread, which would simply print the running time.
Around this, I added the ability to pause, resume and stop the thread so as to demonstrate the basic idea...
public class StopWatchRunnable implements Runnable {
private final Lock pauseLock = new ReentrantLock();
private final Condition pauseCondtion = pauseLock.newCondition();
private final AtomicBoolean isPaused = new AtomicBoolean(false);
private final AtomicBoolean isRunning = new AtomicBoolean(true);
private final StopWatch stopWatch = new StopWatch();
#Override
public void run() {
stopWatch.start();
while (isRunning.get()) {
while (isPaused.get()) {
pauseLock.lock();
stopWatch.pause();
try {
pauseCondtion.await();
} catch (InterruptedException ex) {
} finally {
pauseLock.unlock();
stopWatch.resume();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
Duration duration = stopWatch.getDuration();
String formatted = String.format("%dhrs %02dmins, %02dseconds", duration.toHours(), duration.toMinutesPart(), duration.toSecondsPart());
System.out.println(formatted);
}
}
public void stop() {
pauseLock.lock();
try {
isPaused.set(false);
isRunning.set(false);
} finally {
pauseCondtion.signalAll();
pauseLock.unlock();
}
}
public void pause() {
pauseLock.lock();
try {
isPaused.set(true);
} finally {
pauseLock.unlock();
}
}
public void resume() {
pauseLock.lock();
try {
isPaused.set(false);
} finally {
pauseCondtion.signalAll();
pauseLock.unlock();
}
}
}
Runnable example...
This basically takes the code from above and dumps it into a simple runnable example which demonstrates the pause/resume functionality
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class StopWatchExample {
public static void main(String[] args) throws InterruptedException {
new StopWatchExample();
}
public StopWatchExample() throws InterruptedException {
StopWatchRunnable stopWatch = new StopWatchRunnable();
Thread thread = new Thread(stopWatch);
thread.start();
Thread.sleep(5000);
System.out.println("Pause...");
stopWatch.pause();
Thread.sleep(5000);
System.out.println("Resume...");
stopWatch.resume();
Thread.sleep(5000);
System.out.println("Stop...");
stopWatch.stop();
thread.join();
System.out.println("All done...");
}
public class StopWatch {
private Instant startTime;
private Duration totalRunTime = Duration.ZERO;
public StopWatch start() {
startTime = Instant.now();
return this;
}
public StopWatch stop() {
Duration runTime = Duration.between(startTime, Instant.now());
totalRunTime = totalRunTime.plus(runTime);
startTime = null;
return this;
}
public StopWatch pause() {
return stop();
}
public StopWatch resume() {
return start();
}
public StopWatch reset() {
stop();
totalRunTime = Duration.ZERO;
return this;
}
public boolean isRunning() {
return startTime != null;
}
public Duration getDuration() {
Duration currentDuration = Duration.ZERO;
currentDuration = currentDuration.plus(totalRunTime);
if (isRunning()) {
Duration runTime = Duration.between(startTime, Instant.now());
currentDuration = currentDuration.plus(runTime);
}
return currentDuration;
}
}
public class StopWatchRunnable implements Runnable {
private final Lock pauseLock = new ReentrantLock();
private final Condition pauseCondtion = pauseLock.newCondition();
private final AtomicBoolean isPaused = new AtomicBoolean(false);
private final AtomicBoolean isRunning = new AtomicBoolean(true);
private final StopWatch stopWatch = new StopWatch();
#Override
public void run() {
stopWatch.start();
while (isRunning.get()) {
while (isPaused.get()) {
pauseLock.lock();
stopWatch.pause();
try {
pauseCondtion.await();
} catch (InterruptedException ex) {
} finally {
pauseLock.unlock();
stopWatch.resume();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
Duration duration = stopWatch.getDuration();
String formatted = String.format("%dhrs %02dmins, %02dseconds", duration.toHours(), duration.toMinutesPart(), duration.toSecondsPart());
System.out.println(formatted);
}
}
public void stop() {
pauseLock.lock();
try {
isPaused.set(false);
isRunning.set(false);
} finally {
pauseCondtion.signalAll();
pauseLock.unlock();
}
}
public void pause() {
pauseLock.lock();
try {
isPaused.set(true);
} finally {
pauseLock.unlock();
}
}
public void resume() {
pauseLock.lock();
try {
isPaused.set(false);
} finally {
pauseCondtion.signalAll();
pauseLock.unlock();
}
}
}
}
Related
I have a class extending Thread. Inside this run I have a few method working in while loop. Now I want one of this methods gameSurface.updateBitmapObjects() to work with delay. How to achieve this? Here is my code:
GameThread.java:
public class GameThread<T extends GameSurface> extends Thread {
private boolean isRunning;
private long startTime, loopTime;
private long delay = 33;
private SurfaceHolder surfaceHolder;
private T gameSurface;
public GameThread(SurfaceHolder surfaceHolder, T gameSurface) {
this.surfaceHolder= surfaceHolder;
this.gameSurface = gameSurface;
isRunning = true;
}
#Override
public void run() {
while(isRunning) {
startTime = SystemClock.uptimeMillis();
Canvas canvas = surfaceHolder.lockCanvas(null);
if(canvas != null) {
synchronized (surfaceHolder) {
gameSurface.updateBitmapObjects();
gameSurface.drawMapBitmap(canvas);
((GameMainSurface)gameSurface).drawCoinAndCoins();
((GameMainSurface)gameSurface).drawFieldLines(canvas);
((GameMainSurface)gameSurface).updatePlayersLabels(canvas);
if (((GameMainSurface)gameSurface).isGameMainFragment()) {
((GameMainSurface)gameSurface).setSomeValues();
}
gameSurface.drawObjects(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
loopTime = SystemClock.uptimeMillis() - startTime;
if(loopTime < delay) {
try {
Thread.sleep(delay - loopTime);
}
catch (InterruptedException e) {
Log.e("Interupted ex", e.getMessage());
}
}
}
}
}
GameMainSurface.java:
(...)
public void updateBitmapObjects() {
this.chibi1.update();
(...)
}
MovingObject.java:
// I want this method to work with delay let's say 100 ms
public void update() {
this.colUsing++;
if (colCount == 13) {
if (colUsing >= 9) {
if (rowUsing == ROW_TOP_TO_BOTTOM_CHIBI || rowUsing == ROW_BOTTOM_TO_TOP_CHIBI)
colUsing = 1;
else
colUsing = 0;
}
}
if (colCount == 4) {
if (colUsing >= 4) {
this.colUsing = 0;
}
}
}
I'm writing a program that constantly pings a server. I wrote the code to check it once and put the ping in a JLabel and put it in a method called setPing().
Here is my code
private void formWindowOpened(java.awt.event.WindowEvent evt) {
setPing();
}
That worked but only did it once, so I did:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
for(;;){
setPing();
}
}
But this doesn't even work for the first time.
I didnt put the setPing method because it was too long so here it is:
public String setPing(){
Runtime runtime = Runtime.getRuntime();
try{
Process process = runtime.exec("ping lol.garena.com");
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
int i = 0;
i = line.indexOf("Average");
if(i > 0){
String finalPing = "";
line.toCharArray();
try
{
finalPing = "";
for(int x = i; x < i + 17; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException e)
{
try
{
finalPing = "";
for(int x = i; x < i + 16; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException f)
{
try
{
finalPing = "";
for(int x = i; x < i + 15; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException g){}
}
}
String final1Ping = finalPing.replaceAll("[^0-9]", "");
return final1Ping;
}
}
}catch(IOException e){
}
return "";
}
UPDATE
Just in case this is important, Im using netbeans. I created a form and put this code in the formWindowOpened evt instead of calling it in main:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
ActionListener timerListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new PingWorker().execute();
}
};
Timer timer = new Timer(1000, timerListener);
timer.start();
jLabel1.setText(label.getText());
timer.stop();
// TODO add your handling code here:
}
class PingWorker extends SwingWorker {
int time;
#Override
protected Object doInBackground() throws Exception {
time = pingTime("lol.garena.com");
return new Integer(time);
}
#Override
protected void done() {
label.setText("" + time);
}
};
public JComponent getUI() {
return label;
}
public static int pingTime(String hostnameOrIP) {
Socket socket = null;
long start = System.currentTimeMillis();
try {
socket = new Socket(hostnameOrIP, 80);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
}
long end = System.currentTimeMillis();
return (int) (end - start);
}
Use a Swing Timer for repeating tasks & a SwingWorker for long running tasks. E.G. of both below - it uses a Timer to repeatedly perform a 'long running' task (a ping) in a SwingWorker.
See Concurrency in Swing for more details on the Event Dispatch Thread and doing long running or repeating tasks in a GUI.
This code combines a long running task ('pinging' a server) using SwingWorker invoked from a repeating task (updating the JLabel repeatedly with the times) using a Swing based Timer.
import java.awt.event.*;
import javax.swing.*;
import java.net.Socket;
public class LabelUpdateUsingTimer {
static String hostnameOrIP = "stackoverflow.com";
int delay = 5000;
JLabel label = new JLabel("0000");
LabelUpdateUsingTimer() {
label.setFont(label.getFont().deriveFont(120f));
ActionListener timerListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new PingWorker().execute();
}
};
Timer timer = new Timer(delay, timerListener);
timer.start();
JOptionPane.showMessageDialog(
null, label, hostnameOrIP, JOptionPane.INFORMATION_MESSAGE);
timer.stop();
}
class PingWorker extends SwingWorker {
int time;
#Override
protected Object doInBackground() throws Exception {
time = pingTime();
return new Integer(time);
}
#Override
protected void done() {
label.setText("" + time);
}
};
public static int pingTime() {
Socket socket = null;
long start = System.currentTimeMillis();
try {
socket = new Socket(hostnameOrIP, 80);
} catch (Exception weTried) {
} finally {
if (socket != null) {
try {
socket.close();
} catch (Exception weTried) {}
}
}
long end = System.currentTimeMillis();
return (int) (end - start);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new LabelUpdateUsingTimer();
}
};
SwingUtilities.invokeLater(r);
}
}
You could use a Thread. The problem is you are blocking the main thread, thereby blocking your program. To get around this, start a background Thread to update components repeatedly.
(Note: you need to update GUI components on the EDT, so use SwingUtilities.invokeLater)
(new Thread((new Runnable(){
#Override
public void run(){
while(true){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
refToJLabel.setText(Math.random());
}
});
}
}
}))).start();
I'm writing a program that constantly pings a server. I wrote the code to check it once and put the ping in a JLabel and put it in a method called setPing().
Here is my code
private void formWindowOpened(java.awt.event.WindowEvent evt) {
setPing();
}
That worked but only did it once, so I did:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
for(;;){
setPing();
}
}
But this doesn't even work for the first time.
I didnt put the setPing method because it was too long so here it is:
public String setPing(){
Runtime runtime = Runtime.getRuntime();
try{
Process process = runtime.exec("ping lol.garena.com");
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
int i = 0;
i = line.indexOf("Average");
if(i > 0){
String finalPing = "";
line.toCharArray();
try
{
finalPing = "";
for(int x = i; x < i + 17; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException e)
{
try
{
finalPing = "";
for(int x = i; x < i + 16; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException f)
{
try
{
finalPing = "";
for(int x = i; x < i + 15; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException g){}
}
}
String final1Ping = finalPing.replaceAll("[^0-9]", "");
return final1Ping;
}
}
}catch(IOException e){
}
return "";
}
UPDATE
Just in case this is important, Im using netbeans. I created a form and put this code in the formWindowOpened evt instead of calling it in main:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
ActionListener timerListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new PingWorker().execute();
}
};
Timer timer = new Timer(1000, timerListener);
timer.start();
jLabel1.setText(label.getText());
timer.stop();
// TODO add your handling code here:
}
class PingWorker extends SwingWorker {
int time;
#Override
protected Object doInBackground() throws Exception {
time = pingTime("lol.garena.com");
return new Integer(time);
}
#Override
protected void done() {
label.setText("" + time);
}
};
public JComponent getUI() {
return label;
}
public static int pingTime(String hostnameOrIP) {
Socket socket = null;
long start = System.currentTimeMillis();
try {
socket = new Socket(hostnameOrIP, 80);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
}
long end = System.currentTimeMillis();
return (int) (end - start);
}
Use a Swing Timer for repeating tasks & a SwingWorker for long running tasks. E.G. of both below - it uses a Timer to repeatedly perform a 'long running' task (a ping) in a SwingWorker.
See Concurrency in Swing for more details on the Event Dispatch Thread and doing long running or repeating tasks in a GUI.
This code combines a long running task ('pinging' a server) using SwingWorker invoked from a repeating task (updating the JLabel repeatedly with the times) using a Swing based Timer.
import java.awt.event.*;
import javax.swing.*;
import java.net.Socket;
public class LabelUpdateUsingTimer {
static String hostnameOrIP = "stackoverflow.com";
int delay = 5000;
JLabel label = new JLabel("0000");
LabelUpdateUsingTimer() {
label.setFont(label.getFont().deriveFont(120f));
ActionListener timerListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new PingWorker().execute();
}
};
Timer timer = new Timer(delay, timerListener);
timer.start();
JOptionPane.showMessageDialog(
null, label, hostnameOrIP, JOptionPane.INFORMATION_MESSAGE);
timer.stop();
}
class PingWorker extends SwingWorker {
int time;
#Override
protected Object doInBackground() throws Exception {
time = pingTime();
return new Integer(time);
}
#Override
protected void done() {
label.setText("" + time);
}
};
public static int pingTime() {
Socket socket = null;
long start = System.currentTimeMillis();
try {
socket = new Socket(hostnameOrIP, 80);
} catch (Exception weTried) {
} finally {
if (socket != null) {
try {
socket.close();
} catch (Exception weTried) {}
}
}
long end = System.currentTimeMillis();
return (int) (end - start);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new LabelUpdateUsingTimer();
}
};
SwingUtilities.invokeLater(r);
}
}
You could use a Thread. The problem is you are blocking the main thread, thereby blocking your program. To get around this, start a background Thread to update components repeatedly.
(Note: you need to update GUI components on the EDT, so use SwingUtilities.invokeLater)
(new Thread((new Runnable(){
#Override
public void run(){
while(true){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
refToJLabel.setText(Math.random());
}
});
}
}
}))).start();
As with basically every exchanger task, I have a producer filling up an empty buffer2, a consumer clearing a full buffer1 and when each thread is done, they should exchange their respective buffers.
I am really unsure about where and how to apply the exchange. I defined readyconsumer and readyproducer as booleans, so that a third thread can check whether it's time to exchange the buffers once both are true. This should solve the problem I had doing it with two threads, where the program was stuck with both threads at wait() (which it unfortunately still is).
This is what the code looks like at the moment. Can anyone help me in which class I have to exchange and at what point in the code? Thank you very much in advance!
class Buffer {
static boolean readyconsumer, readyproducer = false;
volatile int count; // number of put actions
static int max = 10;
Buffer() {
count = 0;
}
public synchronized void put() {
if (count == max) {
readyproducer = true;
System.out.println(" wait ");
try {
wait();
} catch (InterruptedException e) {
}
}
count++;
System.out.println("put " + count);
notifyAll();
}
public synchronized void get() {
if (count == 0) {
readyconsumer = true;
System.out.println(" wait");
try {
wait();
} catch (InterruptedException e) {
}
}
count--;
System.out.println("get " + count);
notifyAll();
}
}
class CheckandSwitch extends ProdCon {
public void run() {
while (true) {
if (Buffer.readyconsumer && Buffer.readyproducer) {
try {
ProdCon.buffer2 = exchanger.exchange(ProdCon.buffer1);
ProdCon.buffer1 = exchanger.exchange(ProdCon.buffer2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Buffer.readyconsumer = false;
Buffer.readyproducer = false;
buffer1.count = 0;
buffer2.count = 10;
notifyAll();
}
}
}
}
class Consumer extends ProdCon {
static Buffer buffer;
Consumer(Buffer b) {
super();
buffer = b;
b.count = 10;
}
public void run() {
while (true) {
consume();
buffer.get();
}
}
private void consume() {
System.out.println("consume");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
}
class Producer extends ProdCon {
static Buffer buffer;
Producer(Buffer b) {
super();
buffer = b;
b.count = 0;
}
public void run() {
while (true) {
produce();
buffer.put();
}
}
private void produce() {
System.out.println("produce ");
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
}
import java.util.concurrent.*;
public class ProdCon extends Thread {
static Exchanger<Buffer> exchanger = new Exchanger<Buffer>();
static Buffer buffer1, buffer2 = null;
public static void main(String[] args) {
buffer1 = new Buffer();
buffer2 = new Buffer();
new Consumer(buffer1).start();
new Producer(buffer2).start();
new CheckandSwitch().start();
}
}
You could use an Exchanger.
Here's the code from the javadoc tweaked into a working example.
class DataBuffer<T> {
T data = null;
public boolean isFull() {
return data != null;
}
public boolean isEmpty() {
return data == null;
}
public T get() {
T d = data;
data = null;
return d;
}
public void put(T data) {
this.data = data;
}
}
class FillAndEmpty {
Exchanger<DataBuffer<Integer>> exchanger = new Exchanger<>();
DataBuffer<Integer> initialEmptyBuffer = new DataBuffer<>();
DataBuffer<Integer> initialFullBuffer = new DataBuffer<>();
int countDown = 10;
class FillingLoop implements Runnable {
#Override
public void run() {
DataBuffer currentBuffer = initialEmptyBuffer;
try {
while (currentBuffer != null && countDown > 0) {
addToBuffer(currentBuffer);
if (currentBuffer.isFull()) {
currentBuffer = exchanger.exchange(currentBuffer);
}
}
} catch (InterruptedException ex) {
}
}
private void addToBuffer(DataBuffer<Integer> currentBuffer) {
currentBuffer.put(countDown--);
}
}
class EmptyingLoop implements Runnable {
#Override
public void run() {
DataBuffer<Integer> currentBuffer = initialFullBuffer;
try {
while (currentBuffer != null) {
takeFromBuffer(currentBuffer);
if (currentBuffer.isEmpty()) {
currentBuffer = exchanger.exchange(currentBuffer);
}
}
} catch (InterruptedException ex) {
}
}
private void takeFromBuffer(DataBuffer<Integer> currentBuffer) {
System.out.println(currentBuffer.get());
}
}
void start() {
new Thread(new FillingLoop()).start();
new Thread(new EmptyingLoop()).start();
}
}
public void test() {
System.out.println("Hello");
new FillAndEmpty().start();
}
I have two Timers in java that are scheduled independently. Both timers have different Task.
Timer 1 increments a number and Timer 2 changes the period of Timer 1. Here is the code where I am using two timers
public class Receiver
{
public static int totalBufferCapacity = 1024;
public static int totalPacketsDropped = 0;
public static int totalPacketsServiced = 0;
public static int totalPacketsReceived = 0;
public static int timesBufferGetsFull = 0;
public static int timesIntervelChanged = 0;
public static Socket clientSocket;
public static BufferedReader br;
public static ArrayList<String> buffer;
public static String START = "Start";
public static String STOP = "Stop";
public static String token = "1";
public static boolean flag;
public static Timer timer;
public static int Max = 80;
public static int Min = 40;
public static int rand;
public static PrintStream ps;
public static String packet;
public static Timer timer_2;
public static consumeArrayItems task;
public static void main(String[] args)
{
flag = true;
try
{
init(args[0], args[1]);
while (flag)
{
storePacketInArray();
}
} catch (Exception e)
{
e.printStackTrace();
}
}
public static void init(String localHost, String portNumber)
{
try
{
// inet address which is local host in this case
InetAddress acceptorHost = InetAddress.getByName(localHost);
// port number at which the sender wants to communicate
int serverPortNum = Integer.parseInt(portNumber);
clientSocket = new Socket(acceptorHost, serverPortNum);
} catch (IOException e)
{
e.printStackTrace();
}
}
public static void storePacketInArray()
{
try
{
if (br == null)
{
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
packet = new String(br.readLine());
if (packet.compareToIgnoreCase("Start") == 0)
{
token = START;
buffer = new ArrayList<String>(totalBufferCapacity);
} else if (packet.compareToIgnoreCase("Stop") == 0)
{
stopVaryingTimeSchedular();
stopSchedular();
} else
{
totalPacketsReceived += 1;
buffer.add(packet);
}
computeToken();
} catch (IOException e)
{
e.printStackTrace();
}
}
public static void computeToken()
{
int bufferSize = buffer.size();
if (bufferSize > 0 && bufferSize < totalBufferCapacity)
{
float queueOccupancy = (bufferSize * 100 / totalBufferCapacity);
} else if (bufferSize == totalBufferCapacity)
{
token = "10";
timesBufferGetsFull += 1;
} else if (token.compareToIgnoreCase("Start") == 0)
{
token = START;
startSchedular();
startVaryingTimeSchedular();
} else
{
totalPacketsDropped += 1;
token = "15";
}
sendAcknowledgment();
}
public static void sendAcknowledgment()
{
try
{
if (ps == null)
{
ps = new PrintStream(clientSocket.getOutputStream());
}
String tokenAck = token;
if (packet.compareToIgnoreCase("Stop") != 0)
{
ps.println(tokenAck);
ps.flush();
}
if (!flag)
{
clientSocket.close();
}
} catch (IOException e)
{
e.printStackTrace();
}
}
public static void startSchedular()
{
rand = (int) (Math.random() * (Max - Min));
timer = new Timer();
task = new consumeArrayItems(true);
timer.scheduleAtFixedRate(task, 1, rand);
}
public static void stopSchedular()
{
timer.cancel();
timer.purge();
flag = false;
}
// After every 500 ms service time of packets will vary between Max and Min
public static void startVaryingTimeSchedular()
{
timer_2 = new Timer();
timer_2.scheduleAtFixedRate(new varyServiceTime(), 0, 500);
}
public static void stopVaryingTimeSchedular()
{
timer_2.cancel();
timer_2.purge();
}
}
class consumeArrayItems extends TimerTask
{
public synchronized void run()
{
if (Receiver.buffer.size() > 0)
{
Receiver.totalPacketsServiced += 1;
Receiver.buffer.remove(Receiver.buffer.size() - 1);
}
}
}
class varyServiceTime extends TimerTask
{
public synchronized void run()
{
Receiver.timer.cancel();
Receiver.timer = null;
Receiver.rand = (int) (Math.random() * (Receiver.Max - Receiver.Min));
Receiver.timer = new Timer();
Receiver.timer.scheduleAtFixedRate(new consumeArrayItems(), 0,Receiver.rand);
Receiver.timesIntervelChanged += 1;
}
}
Timer 2 never gets scheduled. What wrong I am doing here.