Make 2 thread counters - counting from start to end value. The value of the counter should be displayed for each count. One thread is set to count to a smaller value than the other. When one of the threads counts to the setpoint, the other stops and completes its execution.
This is my task so I made a solution with a AtomicBoolean run = new AtomicBoolean(true);
/**
* Implements {#link Runnable} and his method {#link Runnable#run} to run until stop is set to true
* and count is less than maxCount.
*/
public class Counter implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(Counter.class);
private static final String MAX_COUNT_EXCEPTION_MESSAGE = "maxCount should be bigger than zero!";
private static final int NUMBER_TO_CHECK_MAX_COUNT_VALIDATION = 1;
private AtomicBoolean run;
private int count;
private int maxCount;
/**
* Constructs a counter with zero count and run equal to true with a specified maxCount.
*
* #param maxCount of the counter
* #throws IllegalArgumentException if maxCount is smaller than 1
*/
Counter(int maxCount, AtomicBoolean run) {
if (maxCount < NUMBER_TO_CHECK_MAX_COUNT_VALIDATION) {
throw new IllegalArgumentException(MAX_COUNT_EXCEPTION_MESSAGE);
}
this.maxCount = maxCount;
this.run = run;
}
/**
* Entry point.
* <p>
* Runs until run is set to false and count is less than maxCount.
* <p>
* On every loop {#link Counter} increment count with 1 and print the count.
*/
#Override
public void run() {
while (count < maxCount && run.get()) {
incrementCount();
logger.info(this + " : " + count);
}
run.set(false);
}
/**
* Used for obtaining current value for the count.
*
* #return count.
*/
int getCount() {
return count;
}
/**
* Increment the count.
*/
private void incrementCount() {
count++;
}
}
/**
* Runs two counters and print the counting for both of them until one reach his maxCount then both are stopped.
*/
public class RunnerTwoCounters {
private static final Logger logger = LoggerFactory.getLogger(RunnerTwoCounters.class);
public static void main(String[] args) throws InterruptedException {
AtomicBoolean run = new AtomicBoolean(true);
Counter counter1 = new Counter(2, run);
Thread thread1 = new Thread(counter1);
Counter counter2 = new Counter(10, run);
Thread thread2 = new Thread(counter2);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
logger.info(counter1 + " " + counter1.getCount());
logger.info(counter2 + " " + counter2.getCount());
}
}
How can I make the same thing to work but without Atomicboolean just to work with Object lock and some synchronization on it?
This does what your recent comment says. Both threads start counting. When one reaches the setPoint, they both stop.
public class ThreadCounting {
int value1;
int value2;
volatile boolean flag = true;
public static void main(String[] args) {
new ThreadCounting().start();
}
public void start() {
int setPoint = 100;
Thread begin = new Thread(() -> {
while(flag && ((value1 = counter1()) <= setPoint)) {
System.out.println(Thread.currentThread().getName() + " counter1 = " + value1);
}
flag = false;
});
Thread finish = new Thread(() -> {
while(flag && ((value2 = counter2()) <= setPoint)) {
System.out.println(Thread.currentThread().getName() +" counter2 = " + value2);
}
flag = false;
});
begin.start();
finish.start();
}
int val1 = 1;
public int counter1() {
return val1++;
}
int val2 = 1;
public int counter2() {
return val2++;
}
}
Related
I'm doing a Java programming assignment which involves bubble sorting a .dat file BetelgeuseNames.dat with strings in it alphabetically. My AP Computer Science A teacher told me my code is correct, but it still gives the wrong output.
There are three classes called BubbleSort, BubbleSortTimer, and StopWatch. The program runs from BubbleSortTimer.
BubbleSort:
import java.util.ArrayList;
import javax.swing.JOptionPane;
import java.io.FileWriter;
import java.io.IOException;
public class BubbleSort {
// Private instance variables:
private ArrayList<String> list;
private int number;
public BubbleSort(ArrayList<String> a_list) {
list = a_list;
}
public void swap(int first, int second) {
String temp1 = list.get(first);
String temp2 = list.get(second);
list.set(first, temp2);
list.set(second, temp1);
}
public int getNumber() {
String numStr;
numStr = JOptionPane.showInputDialog("How many names do you want to sort?");
number = Integer.parseInt(numStr);
return number;
}
public void printSorted() {
try {
FileWriter writer = new FileWriter("sorted.dat");
for (int i = 0; i < number; i++) {
writer.write(list.get(i) + "\n");
}
writer.close();
} catch (IOException exception) {
System.out.println("Error processing file: " + exception);
}
}
public void bubbleSort() {
for (int i = 0; i < number; i++) {
for (int j = 0; j < number - i - 1; j++) {
if (list.get(i).compareTo(list.get(i+1)) > 0) {
swap(i, i + 1);
}
}
}
} // End method
}
BubbleSortTimer:
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.FileReader;
import javax.swing.JOptionPane;
import java.io.IOException;
public class BubbleSortTimer {
private ArrayList<String> list = new ArrayList<String>();
public void readNames() {
try {
FileReader reader = new FileReader("BetelgeuseNames.dat");
BufferedReader in = new BufferedReader(reader);
boolean done = false;
String name;
while (done == false) {
name = in.readLine();
if (name == null) {
done = true;
} else {
list.add(name);
}
}
reader.close();
} catch (IOException exception) {
System.out.println("Error processing file: " + exception);
}
} // End method
public void runSort() {
readNames();
StopWatch timer = new StopWatch();
BubbleSort sorter = new BubbleSort(list);
int number = sorter.getNumber();
timer.start();
sorter.bubbleSort();
timer.stop();
sorter.printSorted();
String msg = "Number of names sorted: " + number + "\nMilliseconds required to sort: " + timer.getElapsedTime() + "\nOutput file is \"sorted.dat\"";
JOptionPane.showMessageDialog(null, msg);
}
public static void main(String[] args) {
BubbleSortTimer bubble = new BubbleSortTimer();
bubble.runSort();
}
}
StopWatch:
/**
* A stopwatch accumulates time when it is running. You can
* repeatedly start and stop the stopwatch. You can use a
* stopwatch to measure the running time of a program.
* from section 18.2 of Horstmann's CCJ
*/
public class StopWatch {
/**
* Constructs a stopwatch that is in the stopped state
* and has no time accumulated.
*/
public StopWatch() {
reset();
}
/**
* Starts the stopwatch. Times starts accumulating now.
*/
public void start() {
if (isRunning) return;
isRunning = true;
startTime = System.currentTimeMillis();
}
/**
* Stops the stopwatch. Time stops accumulating and is
* added to the elapsed time.
*/
public void stop() {
if (!isRunning) return;
isRunning = false;
long endTime = System.currentTimeMillis();
elapsedTime = elapsedTime + endTime - startTime;
}
/**
* Returns the total elapsed time.
#return the total elapsed time
*/
public long getElapsedTime() {
if (isRunning) {
long endTime = System.currentTimeMillis();
elapsedTime = elapsedTime + endTime - startTime;
startTime = endTime;
}
return elapsedTime;
}
/**
* Stops the watch and resets the elapsed time to 0.
*/
public void reset() {
elapsedTime = 0;
isRunning = false;
}
private long elapsedTime;
private long startTime;
private boolean isRunning;
}
Input:
Moewm
Bmlzvltcso
Aqxjor
Wwgjie
Qqqtpivd
Xgyhaerv
Wqpjwdvxjq
Ecsfnow
Zlptuqxctt
Jhtprwvopk
Expected Output:
Aqxjor
Bmlzvltcso
Ecsfnow
Jhtprwvopk
Moewm
Qqqtpivd
Wqpjwdvxjq
Wwgjie
Xgyhaerv
Zlptuqxctt
Actual Output:
Bmlzvltcso
Aqxjor
Moewm
Qqqtpivd
Wwgjie
Wqpjwdvxjq
Ecsfnow
Xgyhaerv
Jhtprwvopk
Zlptuqxctt
This is how Android did (binary) sorting (edited to fix this situation):
public void binarySort() {
int lo = 0; // sort start
for (int start=lo ; start < number; start++) {
String pivot = list.get(start);
// Set left (and right) to the index where list.get(start) (pivot) belongs
int left = 0;
int right = start;
assert left <= right;
/*
* Invariants:
* pivot >= all in [lo, left].
* pivot < all in [right, start].
*/
while (left < right) {
int mid = (left + right) >>> 1;
if (pivot.compareTo(list.get(mid)) < 0)
right = mid;
else
left = mid + 1;
}
assert left == right;
/*
* The invariants still hold: pivot >= all in [lo, left] and
* pivot < all in [left, start], so pivot belongs at left. Note
* that if there are elements equal to pivot, left points to the
* first slot after them -- that's why this sort is stable.
* Slide elements over to make room for pivot.
*/
int n = start - left; // The number of elements to move
// Switch is just reshifter in default case
switch (n) {
case 2: list.set(left + 2,list.get(left + 1));
case 1: list.set(left + 1,list.get(left));
break;
default:
if(n>0){
list.add(left,list.remove(left+n));
}
}
list.set(left,pivot);
}
}
This is how you can do (bubble) sorting:
public void bubbleSort() {
for (int i = 0; i < number; i++) {
for (int j = i + 1; j < number; j++) {
if (list.get(i).compareTo(list.get(j)) > 0) {
swap(i, j);
}
}
}
}
BUBBLE SORTING V/S BINARY SORTING:
OFF TOPIC: As you can compare above, bubble sorting is easier to code/read/understand and is also faster as compared to binary sorting, because binary sorting (actually) uses array recreation many times which ofcourse takes more time compared to swap.
Because there is a problem with your bubbleSort() method. Please try this way.
public void bubbleSort() {
for (int i = 0; i < number; i++) {
for (int j = 1; j < number - i; j++) {
if (list.get(j - 1).compareTo(list.get(j)) > 0) {
swap(j - 1, j);
}
}
}
}
I'm reading the book Core java by Cay S. Horstmann. I'm confused with this code in the section concurrency.
We construct a new thread and pass our Runnable task to it, I understand up until this. The part that confuses me is that, we call the start() method to these new threads on after another. My question is that when does the first call to the start() method returns to main() method. Is it after the new thread has finished its task or does it returns while that new thread is running the task?
import java.util.Arrays;
public class Main{
public static final int DELAY = 10;
public static final int STEPS = 100;
public static final double MAX_AMOUNT = 1000;
public static void main(String[] args) {
var bank = new Bank(4, 100000);
Runnable task1 = () -> {
try {
for (int i = 0; i < STEPS; i++){
double amount = MAX_AMOUNT * Math.random();
bank.transfer(0, 1, amount);
Thread.sleep((int) (DELAY * Math.random()));
}
}catch (InterruptedException e) {
}
};
Runnable task2 = () ->{
try{
for (int i = 0; i < STEPS; i++){
double amount = MAX_AMOUNT * Math.random();
bank.transfer(2, 3, amount);
Thread.sleep((int) (DELAY * Math.random()));
}
}
catch (InterruptedException e){
}
};
new Thread(task1).start();
new Thread(task2).start();
}
}
class Bank{
private final double[] accounts;
/**
* Constructs the bank.
* #param n the number of accounts
* #param initialBalance the initial balance for each account
*
**/
public Bank(int n, double initialBalance){
accounts = new double[n];
Arrays.fill(accounts, initialBalance);
}
/**
* Transfers money from one account to another.
* #param from the account to transfer from
* #param to the account to transfer to 27
* #param amount the amount to transfer 28
**/
public void transfer(int from, int to, double amount){
if (accounts[from] < amount) return;
System.out.print(Thread.currentThread());
accounts[from] -= amount;
System.out.printf(" %10.2f from %d to %d", amount, from, to);
accounts[to] += amount;
System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
}
/**
* Gets the sum of all account balances.
* #return the total balance 42
**/
public double getTotalBalance(){
double sum = 0;
for (double a : accounts)
sum += a;
return sum;
}
/**
* Gets the number of accounts in the bank.
* * #return the number of accounts 56
**/
public int size(){
return accounts.length;
}
}
The start method returns immediately & the Main Thread continues running.
You can see this happening with this little Proggy:
import java.time.Duration;
import java.time.ZonedDateTime;
public class Runner {
public static void main(final String[] args) throws Exception {
final Runnable runner = () -> {
System.out.println(ZonedDateTime.now() + " " + Thread.currentThread().getName() + " Running...");
sleep(Duration.ofSeconds(9));
System.out.println(ZonedDateTime.now() + " " + Thread.currentThread().getName() + " Done.");
};
System .out.println(ZonedDateTime.now() + " " + Thread.currentThread().getName() + " starting Thread 1...");
new Thread(runner).start();
System .out.println(ZonedDateTime.now() + " " + Thread.currentThread().getName() + " starting Thread 2...");
new Thread(runner).start();
sleep(Duration.ofSeconds(3));
System .out.println(ZonedDateTime.now() + " " + Thread.currentThread().getName() + " done.");
}
private static void sleep(final Duration duration) {
try {
Thread.sleep(duration.toMillis());
}
catch (final InterruptedException e) {}
}
}
Start method finish immediately after creating new thread. The result of start method is two threads that are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).
The start() method internally calls the run() method of Runnable interface to execute the code specified in the run() method in a separate thread.
Execution of starting thread in main thread is like any other statement. If you want to wait for the thread to finish you must use join method on it:
Thread t1 = new Thread(task1).start();
t1.join();
Thread ends its execution when its run method finish.
Yes it returns when the moment it handles the new run method to the new thread.
Then the thread pooling handles the control flow of the threads. Refer to threads and concurrency in java
I need to know how frequency different events occur. For example how many HTTP requests have occurred in the last 15 minutes. Because there can be a large count of events (millions) this must be use a limited amount of memory.
It there any util class in Java that can do this?
How can I implement this self in Java?
Theoretical usage code can look like:
FrequencyCounter counter = new FrequencyCounter( 15, TimeUnit.Minutes );
...
counter.add();
...
int count = counter.getCount();
Edit: It must be a real time value which can changed thousand times the minute and will be query thousands times the minute. That a database or file based solution are not possible.
Here is my implementation of such a counter. The memory usage with the default precision is fewer as 100 bytes. The memory usage is independent of the event count.
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A counter that counts events within the past time interval. All events that occurred before this interval will be
* removed from the counter.
*/
public class FrequencyCounter {
private final long monitoringInterval;
private final int[] details;
private final AtomicInteger currentCount = new AtomicInteger();
private long startInterval;
private int total;
/**
* Create a new instance of the counter for the given interval.
*
* #param interval the time to monitor/count the events.
* #param unit the time unit of the {#code interval} argument
*/
FrequencyCounter( long interval, TimeUnit unit ) {
this( interval, unit, 16 );
}
/**
* Create a new instance of the counter for the given interval.
*
* #param interval the time to monitor/count the events.
* #param unit the time unit of the {#code interval} argument
* #param precision the count of time slices for the for the measurement
*/
FrequencyCounter( long interval, TimeUnit unit, int precision ) {
monitoringInterval = unit.toMillis( interval );
if( monitoringInterval <= 0 ) {
throw new IllegalArgumentException( "Interval mus be a positive value:" + interval );
}
details = new int[precision];
startInterval = System.currentTimeMillis() - monitoringInterval;
}
/**
* Count a single event.
*/
public void increment() {
checkInterval( System.currentTimeMillis() );
currentCount.incrementAndGet();
}
/**
* Get the current value of the counter.
*
* #return the counter value
*/
public int getCount() {
long currentTime = System.currentTimeMillis();
checkInterval( currentTime );
long diff = currentTime - startInterval - monitoringInterval;
double partFactor = (diff * details.length / (double)monitoringInterval);
int part = (int)(details[0] * partFactor);
return total + currentCount.get() - part;
}
/**
* Check the interval of the detail counters and move the interval if needed.
*
* #param time the current time
*/
private void checkInterval( final long time ) {
if( (time - startInterval - monitoringInterval) > monitoringInterval / details.length ) {
synchronized( details ) {
long detailInterval = monitoringInterval / details.length;
while( (time - startInterval - monitoringInterval) > detailInterval ) {
int currentValue = currentCount.getAndSet( 0 );
if( (total | currentValue) == 0 ) {
// for the case that the counter was not used for a long time
startInterval = time - monitoringInterval;
return;
}
int size = details.length - 1;
total += currentValue - details[0];
System.arraycopy( details, 1, details, 0, size );
details[size] = currentValue;
startInterval += detailInterval;
}
}
}
}
}
The best way I can think to implement this is using another "time counting" thread.
If you're concerned about the amount of memory, you can add a threshold for the size of eventsCounter (Integer.MAX_VALUE seems like the natural choice).
Here's an example for an implementation, that is also thread-safe:
public class FrequencyCounter {
private AtomicInteger eventsCounter = new AtomicInteger(0);
private int timeCounter;
private boolean active;
public FrequencyCounter(int timeInSeconds) {
timeCounter = timeInSeconds;
active = true;
}
// Call this method whenever an interesting event occurs
public int add() {
if(active) {
int current;
do {
current = eventsCounter.get();
} while (eventsCounter.compareAndSet(current, current + 1));
return current + 1;
}
else return -1;
}
// Get current number of events
public int getCount() {
return eventsCounter.get();
}
// Start the FrequencyCounter
public void run() {
Thread timer = new Thread(() -> {
while(timeCounter > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
timeCounter --;
}
active = false;
});
timer.start();
}
}
How about a scheduled executor service.
class TimedValue{
int startValue;
int finishedValue;
TimedValue(int start){
startValue = start;
}
}
List<TimedValue> intervals = new CopyOnWriteArrayList<>();
//then when starting a measurement.
TimeValue value = new TimedValue();
//set the start value.
Callable<TimedValue> callable = ()->{
//performs the task.
value.setValueAtFinish(getCount());
return value;
}
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
ScheduledFuture<TimedValue> future = executor.schedule(
callable,
TimeUnit.MINUTES,
15);
executor.schedule(()->itervals.add(
future.get(),
TimeUnit.MINUTES,
future.getDelay(TimeUnit.MINUTES
);
This is a bit of a complicated method.
I would probably just have a List<LoggedValues> and accumulate values in that list at a fixed rate. Then it could be inspected whenever you want to know an intervals.
public class TaskThreadDemo {
public static void main(String[] args) {
// Create tasks
Runnable printA = new PrintChar('a', 100);
Runnable printB = new PrintChar('b', 100);
Runnable print100 = new PrintNum(100);
// Create threads
Thread thread1 = new Thread(printA);
Thread thread2 = new Thread(printB);
Thread thread3 = new Thread(print100);
// Start threads
thread1.start();
thread2.start();
thread3.start();
}
}
// The task for printing a specified character in specified times
class PrintChar implements Runnable {
private char charToPrint; // The character to print
private int times; // The times to repeat
/** Construct a task with specified character and number of
* times to print the character
*/
public PrintChar(char c, int t) {
charToPrint = c;
times = t;
}
/** Override the run() method to tell the system
* what the task to perform
*/
public void run() {
for (int i = 0; i < times; i++) {
System.out.print(charToPrint);
}
}
}
// The task class for printing number from 1 to n for a given n
class PrintNum implements Runnable {
private int lastNum;
/** Construct a task for printing 1, 2, ... i */
public PrintNum(int n) {
lastNum = n;
}
/** Tell the thread how to run */
public void run() {
for (int i = 1; i <= lastNum; i++) {
System.out.print(" " + i);
}
}
}
Here is the previous code, when the code run, the output will be aaaaaa.....bbbbbbbb.........1 2 3 4 5 ......100
How if i wan to change the output become :
1 2 abbbbaaaaaaaaabbbbbbbbbb 3 4 5 6 7 aaaaaabbbb 8 9 10 aaaaaaaaaaaabbbbbbbbbbaaa 11 12 13 14 ........ bbaaaabbaaaa ...... 100
Thanks.
I want have a Producer Consumer Problem where only the newest Item shall be consumed.
This problem may have a different name, but I couldn't figure it out!
The producer thread(s) produce elements in a non-blocking fashion by overriting any old items.
The single consumer thread should wait for an element to be created and consume it.
I thought about using a blocking queue but the java implementation does not allow for overriding old elements. A circular buffer (like from the commons libary) doesn't work either because its not blocking for the consumer.
Is there a datastructure that serves this purpose or do I need to find a better way?
It might also be possible to solve this with low level synchronization tools like locks but I couldn't figure out how to do it.
There is no need for a special data structure. Just use the methods available in Object. They are quite good in this situation, because the blocking consumer:
class ItemHolder<T> {
private T item;
public synchronized void produce(T item) {
this.item = item;
notify();
}
public synchronized T consume() {
while (item == null) {
wait();
}
T result = item;
item = null;
return result;
}
}
Efficient Circular Buffer in Java
Overwriting Circular buffers are great data structures to use if you would like to operate on a recent window of data. Elements are added and removed FIFO like a Queue, except additions on full buffers will cause the oldest (head of the queue) element to be removed.
import java.util.NoSuchElementException;
/**
* Thread safe fixed size circular buffer implementation. Backed by an array.
*
* #author brad
*/
public class ArrayCircularBuffer<T> {
// internal data storage
private T[] data;
// indices for inserting and removing from queue
private int front = 0;
private int insertLocation = 0;
// number of elements in queue
private int size = 0;
/**
* Creates a circular buffer with the specified size.
*
* #param bufferSize
* - the maximum size of the buffer
*/
public ArrayCircularBuffer(int bufferSize) {
data = (T[]) new Object[bufferSize];
}
/**
* Inserts an item at the end of the queue. If the queue is full, the oldest
* value will be removed and head of the queue will become the second oldest
* value.
*
* #param item
* - the item to be inserted
*/
public synchronized void insert(T item) {
data[insertLocation] = item;
insertLocation = (insertLocation + 1) % data.length;
/**
* If the queue is full, this means we just overwrote the front of the
* queue. So increment the front location.
*/
if (size == data.length) {
front = (front + 1) % data.length;
} else {
size++;
}
}
/**
* Returns the number of elements in the buffer
*
* #return int - the number of elements inside this buffer
*/
public synchronized int size() {
return size;
}
/**
* Returns the head element of the queue.
*
* #return T
*/
public synchronized T removeFront() {
if (size == 0) {
throw new NoSuchElementException();
}
T retValue = data[front];
front = (front + 1) % data.length;
size--;
return retValue;
}
/**
* Returns the head of the queue but does not remove it.
*
* #return
*/
public synchronized T peekFront() {
if (size == 0) {
return null;
} else {
return data[front];
}
}
/**
* Returns the last element of the queue but does not remove it.
*
* #return T - the most recently added value
*/
public synchronized T peekLast() {
if (size == 0) {
return null;
} else {
int lastElement = insertLocation - 1;
if (lastElement < 0) {
lastElement = data.length - 1;
}
return data[lastElement];
}
}
}
Here is Circular Bounded Queue which is (supposed to be)thread safe and provides a blocking take operation.
public class CircularQueue<T> {
private final int MAX_SIZE;
private final AtomicReferenceArray<T> buffer;
private final AtomicInteger start;
private final AtomicInteger end;
private final AtomicInteger len;
private final ReentrantLock rwlock;
private final Condition readCondition;
public CircularQueue(int size) {
MAX_SIZE = size;
buffer = new AtomicReferenceArray<T>(size);
start = new AtomicInteger(0);
end = new AtomicInteger(0);
len = new AtomicInteger(0);
rwlock = new ReentrantLock(true);
readCondition = rwlock.newCondition();
}
/**
* Adds to tail of the queue
*/
public void put(T val) {
try {
rwlock.lock();
buffer.set(end.get(), val);
end.set((end.get() + 1) % MAX_SIZE);
if (len.get() == MAX_SIZE) { // overwrite
start.set((start.get() + 1) % MAX_SIZE);
} else {
len.incrementAndGet();
}
readCondition.signal();
} finally {
rwlock.unlock();
}
}
/**
* Blocking removeFront operation
* #return
*/
public T take() {
T val = null;
try {
rwlock.lock();
while (len.get() == 0) {
try {
readCondition.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
val = buffer.get(start.get());
buffer.set(start.get(), null);
start.set((start.get() + 1) % MAX_SIZE);
len.decrementAndGet();
} finally {
rwlock.unlock();
}
return val;
}
public int size() {
int curLen = 0;
try {
rwlock.lock();
curLen = len.get();
} finally {
rwlock.unlock();
}
return curLen;
}
}
There are many operations which are yet to be added like poll, offer etc. But you can test this out with some threads :
It is going to hang your JVM if it runs correctly.
public static void main(String[] args) {
final int MAX_QUEUE_SIZE = 4;
final CircularQueue<Integer> q = new CircularQueue<Integer>(MAX_QUEUE_SIZE);
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < MAX_QUEUE_SIZE; ++i) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Putting: from " + Thread.currentThread().getName() + " " + i);
q.put(i);
}
for (int i = 0; i < MAX_QUEUE_SIZE; ++i) {
System.out.println("Trying to get from " + Thread.currentThread().getName() + " " + q.take());
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 10; i < 10 + MAX_QUEUE_SIZE; ++i) {
try {
Thread.sleep(1001);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Putting: from " + Thread.currentThread().getName() + " " + i);
q.put(i);
}
for (int i = 0; i < MAX_QUEUE_SIZE; ++i) {
System.out.println("Trying to get from " + Thread.currentThread().getName() + " " + q.take());
}
}
}).start();
}
Your output should probably match
Putting: from Thread-0 0
Putting: from Thread-1 10
Putting: from Thread-0 1
Putting: from Thread-1 11
Putting: from Thread-0 2
Putting: from Thread-1 12
Putting: from Thread-0 3
Trying to get from Thread-0 11
Trying to get from Thread-0 2
Trying to get from Thread-0 12
Trying to get from Thread-0 3
Putting: from Thread-1 13
Trying to get from Thread-1 13
The other take operations from Thread-1 are waiting for a corresponding put operation since Thread-1 is slightly slower than Thread-0.
Simplest solution that Java provides for this is this:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newSingleThreadExecutor()
Per doc:
"Creates an Executor that uses a single worker thread operating off an unbounded queue, and uses the provided ThreadFactory to create a new thread when needed"