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.
Related
I've implemented a thread that get user input by keyboard. However, when user sets input my program returns an IllegalThreadStateException error, at line 23.
import java.util.Scanner;
public class Main {
static MyThread myThread = new MyThread();
static public boolean answered = false;
public static void main(String[] args) {
String s = "";
while (!s.equalsIgnoreCase("q")) {
int seconds = 0, average = 5;
if (seconds > average) {
myThread.stop();
String phrase = choosePhrase(seconds, average);
System.out.println(phrase);
Scanner keyboard = new Scanner(System.in);
s = keyboard.nextLine();
} else {
long createdMillis = System.currentTimeMillis();
myThread.start();
while (!answered && seconds < average) {
long nowMillis = System.currentTimeMillis();
seconds = (int) ((nowMillis - createdMillis) / 1000);
}
}
}
}
private static String choosePhrase(int seconds, int average) {
if (seconds > average + 10) {
return "¿D?";
} else if (seconds > average + 5) {
return "¿E?";
} else {
return "¿F?";
}
}
}
class MyThread extends Thread {
static String[] questions = {"¿A?", "¿B?", "¿C?"};
public void run() {
System.out.println("MyThread running");
Double d = Math.random() * 100;
int n = (int) (Math.ceil(d) % 3);
String question = questions[n];
System.out.println(question);
Scanner keyboard = new Scanner(System.in);
String s = keyboard.nextLine();
stop();
}
}
Why am I getting this exception? How do I make the thread gets and exits correctly to main function?
To make a thread exits proprely you have to use myThread.interrupt();
I've solved the issue with your suggestions:
import javax.swing.JOptionPane;
public class Main {
public static void main(String[] args) {
Latency latency = new Latency();
latency.start();
}
}
class Latency {
int seconds = 0, average = 5;
MyThread myThread;
ObjectToPass o = new ObjectToPass();
public void start() {
String s = "";
Thread t = null;
while (!s.equalsIgnoreCase("q")) {
// The program has just begun, or user has answered a question,
// or term has expired.
seconds = 0;
if (myThread != null) {
myThread.shutdown();
myThread = null;
}
if (o.answered) {
o.answered = false;
myThread = new MyThread(o, new String[]{"¿A?", "¿B?", "¿C?"});
} else {
myThread = new MyThread(o, new String[]{"¿D?", "¿E?", "¿F?"});
}
t = new Thread(myThread);
t.start();
long createdMillis = System.currentTimeMillis();
while (!this.o.getPlay() && seconds < average) {
long nowMillis = System.currentTimeMillis();
seconds = (int) ((nowMillis - createdMillis) / 1000);
}
}
}
}
class ObjectToPass {
boolean answered = true;
public synchronized boolean getPlay() {
return answered;
}
public synchronized void setPlay(boolean answered) {
this.answered = answered;
}
}
class MyThread implements Runnable {
ObjectToPass o;
static String[] questions;
public MyThread(ObjectToPass o, String[] questions) {
this.o = o;
this.questions = questions;
}
public void run() {
// System.out.println("MyThread running");
Double d = Math.random() * 100;
int n = (int) (Math.ceil(d) % 3);
String question = questions[n];
System.out.println(question);
// Scanner keyboard = new Scanner(System.in);
// String s = keyboard.nextLine();
Object[] options = {"Yes", "No"};
int oo = JOptionPane.showOptionDialog(null,
question, "Question", JOptionPane.YES_OPTION,
JOptionPane.NO_OPTION, null, options, options[0]);
this.o.setPlay(true);
}
public void shutdown() {
Thread.currentThread().interrupt();
return;
}
}
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();
}
}
}
}
I have been writing a race code for a class I am in that races two threads, a tortoise and a hare. I can get both of them to run for 80 units but I don't know how to write a code that determines and outputs who the winner is. Any help would be appreciated because I am super new to coding.
I have the tortoise, hare, and raceParticipant classes. My driver class looks like this, where I would assume I put the winner code?
package Domain;
public class Driver
{
public static void main(String[] args)
{
Hare bob = new Hare();
Tortoise fred = new Tortoise();
int winDistance = 80;
do {
bob.sprint();
fred.sprint();
bob.display();
fred.display();
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}while(bob.getTotalDistance() < winDistance && fred.getTotalDistance() < winDistance);
}
}
My sprint method is
public int sprint()
{
int sleep = generator.nextInt(100);
int sprintDistance = 0;
if (sleep > sleepPercent)
{
sprintDistance = generator.nextInt(topSpeed) + 1;
}
totalDistance +=sprintDistance;
return sprintDistance;
}
I don't see you creating a new thread anywhere.
You can create a Hare class like this:
public class Hare implements Runnable {
private static final int SLEEP_DURATION = 3000; //milliseconds
private static final int SPEED = 3; //units per second
private int distanceToRun;
private final RaceFinishListener listener;
public Hare(int distanceToRun, RaceFinishListener listener) {
this.distanceToRun = distanceToRun;
this.listener = listener;
}
#Override
public void run() {
do {
distanceToRun -= SPEED;
try {
Thread.sleep(SLEEP_DURATION);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (distanceToRun > 0);
listener.onRaceFinished(getClass().getSimpleName());
}
}
and a similar Tortoise class with these variables:
private static final int SLEEP_DURATION = 1000; //sleeps less
private static final int SPEED = 1; //but is slow
Then create a listener to get notified when someone has finished:
public interface RaceFinishListener {
void onRaceFinished(String finisher);
}
and finally your main class:
public class Test implements RaceFinishListener {
private String winner;
private static final int DISTANCE_TO_RUN = 10;
public static void main(String[] args) {
new Test().race();
}
private void race() {
Hare bob = new Hare(DISTANCE_TO_RUN, this);
Tortoise fred = new Tortoise(DISTANCE_TO_RUN, this);
new Thread(bob).start();
new Thread(fred).start();
}
#Override
public void onRaceFinished(String finisher) {
synchronized (this) {
if (winner == null) {
winner = finisher;
System.out.println(finisher + " is the winner!");
} else {
System.out.println(finisher + " lost.");
}
}
}
}
Output
Tortoise is the winner!
Hare lost.
After this line:
}while(bob.getTotalDistance() < winDistance && fred.getTotalDistance() < winDistance);
You would just have:
boolean bobWins = (bob.getTotalDistance() >= winDistance);
boolean fredWins = (fred.getTotalDistance() >= winDistance);
if (bobWins && fredWins) {
System.out.println("It's a tie");
}
else if (bobWins) {
System.out.println("Bob Wins");
}
else {
System.out.println("Fred Wins");
}
I want to use two threads to print Floyd triangle(say one thread prints the number and the other prints the number in the line) as below.
and so forth until the max number which is 15 in this case.
I tried following but it keeps on printing numbers one on each line
public class MyThread extends Thread{
static volatile int lineNumber = 1;
public static void main(String... args) {
PrintFloyd print = new PrintFloyd();
Thread t1 = new Thread(new TaskHandler(print, 10), "T1");
Thread t2 = new Thread(new TaskHandler(print, 10), "T2");
t1.start();
t2.start();
}
}
class TaskHandler implements Runnable {
static volatile int i = 1;
static volatile int lineCount = 1;
static volatile int lineNumber = 1;
private int max;
private PrintFloyd print;
TaskHandler(PrintFloyd print2, int max) {
this.print = print2;
this.max = max;
}
#Override
public void run() {
System.out.println(">>>>" + Thread.currentThread().getName());
while(i < max){
if (Thread.currentThread().getName().equals("T1")){
print.printNumber(i);
} else {
print.breakLine();
}
}
}
}
class PrintFloyd {
boolean isBreakPoint = false;
public void printNumber(int i) {
synchronized(this){
while (isBreakPoint == false) {
try {
wait();
} catch (InterruptedException ex) {
}
System.out.print(i++ + " ");
isBreakPoint = false;
notifyAll();
}
}
}
public void breakLine(){
synchronized(this){
while (isBreakPoint == true) {
try {
wait();
} catch (InterruptedException ex) {
}
}
System.out.println();
isBreakPoint = true;
notifyAll();
}
}
}
The following code would help:
public class PrintPatternWith2Threads {
final static int MAX = 15;
final static String itemWriterName = "itemWriter";
final static String newLineWriterName = "newLineWriter";
public static void main(String[] args) {
Printer print = new Printer(MAX);
Thread itemWriter = new Thread(new ItemWriter(print), itemWriterName);
itemWriter.start();
Thread newLineWriter = new Thread(new NewLineWriter(print), newLineWriterName);
newLineWriter.start();
}
}
class ItemWriter implements Runnable {
private Printer print;
ItemWriter(Printer print) {
this.print = print;
}
public void run() {
while (print.current <= print.MAX) {
print.printNumber();
}
}
}
class NewLineWriter implements Runnable {
private Printer print;
NewLineWriter(Printer print) {
this.print = print;
}
public void run() {
while (print.current <= print.MAX) {
print.printNewLine();
}
}
}
class Printer {
public final int MAX;
public int current = 1;
public int itemsInALine = 1;
Printer(int max) {
this.MAX = max;
}
public void printNumber() {
synchronized(this) {
for(int i = current; i < current + itemsInALine && i <= MAX; i++) {
System.out.print(i + " ");
}
this.current = current + itemsInALine;
itemsInALine++;
notifyAll();
try {
if(this.current < MAX) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void printNewLine() {
synchronized(this) {
System.out.println();
notifyAll();
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
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();
}