Pattern to communicate with a thread - java

I have a class OuterClass that contains a List and there is a thread ListWorker that is started in OuterClass that is adding some elements to the list. Based on a function call to OuterClass , it should be able to inform the thread to delete elements. What is the best practise? The intention is not to have a blocking data structure (no synchronization) and therefore having a single thread work on List.
Class OuterClass {
List<String> list = new ArrayList<String>();
ListWorker worker = new ListWorker(list);
deleteLastElement() {
worker.setDeleteLastElement(true);
}
}
The worker
ListWorker implements Runnable {
private List<String> list;
private volatile boolean deleteLastElement;
public void setDeleteLastElement(boolean deleteLastElement) {
this.deleteLastElement = deleteLastElement;
}
public ListWorker(List<String> list) {
this.list = list;
}
public void run() {
while(true) {
//add random elements
if(deleteLastElement) {
//delete last element
//set the boolean now to false
}
}
}

This is untested and may need some additional Exception handling but that's roughly it:
ListWorker implements Runnable {
private interface Command{
void execute();
}
private List<String> list;
private BlockingQueue<ListWorker.Command> work; // give it a Blocking Queue impl.
private volatile boolean bAddRandomElements;
public synchronized void deleteLastElement() {
work.add( new Command(){
#Override
public void execute(){ /* delete Last Element of the list */ }
} );
}
public synchronized void startAddingRandom() {
work.add( new Command(){
#Override
public void execute(){ /* set switch bAddRandomElements */ }
} );
}
public synchronized void stopAddingRandom() {
work.add( new Command(){
#Override
public void execute(){ /* reset switch bAddRandomElements */ }
} );
}
public synchronized void terminate() {
work.add( new Command(){
#Override
public void execute(){ /* interrupt thread */ }
} );
}
public ListWorker(List<String> list) {
this.list = list;
}
public void run() {
while(!Thread.interrupted()) {
Command c = null;
if( bAddRandomElements ){
/* add random, assuming you add one random entry per iteration ... */
c = work.poll( /*maybe specify timeout*/ ); // No command - just go on with it! We'll block in next iteration if bAddRandomElements is reset.
}else{
c = work.take(); // blocks until there is a command in queue.
}
if ( null != c ) c.execute();
}
}

Related

Adding and removing element from list concurrently

I want to create two threads that one adds elements into ArrayList (or vector) and the other removes elements from this list concurrently. For example, if thread1 adds 20 elements into the list, then thread2 starts removing at the same time until total elements are removed, but these two threads must be work at the same time.
I wrote a producer (adding to the list) thread. In this thread, when the number of elements added to the list is greater than 5 or any number, so new thread must be started but in here I am stuck. I will mark the point that I was stuck.
public class Test{
public static void main(String[] args) {
Data d = new Data();
Thread t = new Thread(new producer(d));
t.start();
}
}
class producer implements Runnable{
Data d;
Data d2;
Object lck;
public producer(Data dd)
{
d=dd;
}
#Override
public void run()
{
for (int i=0;i<100;++i ) {
synchronized (d){
d.a.add(i);
// if i is greater than 5,
// start consumer thread
// which remove elements from ArrayList.
// but how ??
Thread t = new Thread(new Runnable(){
#Override
public void run()
{
//if(d.a.isEmpty())
//wait the adder thread
}
});
t.start();
}
}
}
}
class Data{
ArrayList<Integer> a; // or vector
public Data()
{
a = new ArrayList<>();
}
}
How can I implement a remover thread that removes all elements in the list with the same time with adder thread and synchronize them?
You can try concurrent package of java .
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CopyOnWriteArrayList.html
You are using synchronized block in thread which will not help in this case. Method in collection or shared data should be synchronized as it will be accessed by multiple thread
In your code, you are creating 100 consumer thread in producer class within synchronized block. This is not efficient way to utilize parallelism using multi-threading. You are creating one thread for one data to be consumed. Once the data is consumed your thread will be in DEAD state and will not be useful to consume other incoming data, this is wastage of resource as well as requires more time to solve problem.
Take reference of below code to solve your consumer producer problem.
import java.util.*;
class Data {
final List<Integer> a;
public Data() {
a = new ArrayList<>();
}
}
public class Producer implements Runnable {
private final Data data;
public Producer(Data data) {
this.data = data;
}
#Override
public void run() {
for (int i = 0; i < 100; i++) {
synchronized (data) {
data.a.add(i);
}
}
}
}
public class Consumer implements Runnable {
private Data data;
private boolean isThreadEnabled = true;
public Consumer(Data data) {
this.data = data;
}
#Override
public void run() {
while (isThreadEnabled) {
synchronized (data) {
if (!data.a.isEmpty()) {
System.out.println(data.a.remove(0));
}
}
}
}
public void stopConsumer() {
isThreadEnabled = false;
}
}
public class ThreadsMain {
public static void main(String args[]) {
try {
Data data = new Data();
Consumer consumerRunnable = new Consumer(data);
Thread producer = new Thread(new Producer(data));
Thread consumer = new Thread(consumerRunnable);
producer.start();
consumer.start();
producer.join();
try {
//wait for consumer to consume data and then stop the thread
Thread.sleep(1000);
consumerRunnable.stopConsumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

Synchronization of methods of differents classes

I have two classes each with one method.
class A {
private void insert(String usedId){
// ...
}
}
class B {
private void refresh(String userId){
// ...
}
}
Each method is called from a different Thread. They are called from different Threads for different userIds.
I need to lock the first method when second is called and vise versa for the same userId.
Is the best choice to hold a List of ids and set the lock?
We introduce a LockDispenser. You pass this object to all As and Bs you want to have thread safe. It will provide Lock objects with createLock(String forId) which need to be released after use by calling releaseLock(String forId).
public class LockDispenser {
private final Map<String, Lock> dispenser = new LinkedHashMap<>();
public Object createLock(String forId) {
synchronized (dispenser) {
if (!dispenser.containsKey(forId)) {
dispenser.put(forId, new Lock());
}
Lock lock = dispenser.get(forId);
lock.referenceCounter++;
return lock;
}
}
public void releaseLock(String forId) {
synchronized (dispenser) {
Lock lock = dispenser.get(forId);
lock.referenceCounter--;
if (lock.referenceCounter == 0) {
dispenser.remove(forId);
}
}
}
public static class Lock {
private int referenceCounter = 0;
}
}
Now the actual thread safety comes from using the Lock in a synchronized block.
public class A {
private LockDispenser dispenser;
public A(LockDispenser dispenser) {
this.dispenser = dispenser;
}
private void insert(String userId) {
synchronized (dispenser.createLock(userId)) {
// code
}
dispenser.releaseLock(userId); // consider putting this in a finally block
}
}
public class B {
private LockDispenser dispenser;
public B(LockDispenser dispenser) {
this.dispenser = dispenser;
}
private void refresh(String userId) {
synchronized (dispenser.createLock(userId)) {
// code
}
dispenser.releaseLock(userId); // consider putting this in a finally block
}
}
Make sure releaseLock(String forId) is called even if an Exception is thrown. You can do this by putting it into a finally block.
And create them like such:
public static void main(String... args) {
LockDispenser fooLock = new LockDispenser();
A fooA = new A(fooLock);
B fooB = new B(fooLock);
LockDispenser barLock = new LockDispenser();
A barA = new A(barLock);
B barB = new B(barLock);
}
fooA and fooB are thread safe with each other and so are barA and barB.

Critical sections - Thinking in Java example

I read now book Thinking in Java, chapter about critical sections and I cannot understand an example, because I got exceptions which are not described in the book. An example looks like below:
class Pair {
private int x, y;
public Pair(int x, int y) {
this.x = x;
this.y = y;
}
public Pair() {
this(0, 0);
}
public int getX() { return x; }
public int getY() { return y; }
public void incrementX() { x++; }
public void incrementY() { y++; }
public class PairValuesNotEqualException extends RuntimeException {
public PairValuesNotEqualException() {
super("Values are not equal: " + Pair.this);
}
}
public void checkState() {
if (x != y) {
throw new PairValuesNotEqualException();
}
}
}
abstract class PairManager {
AtomicInteger checkCounter = new AtomicInteger(0);
protected Pair p = new Pair();
public synchronized Pair getPair() {
// Make copies to protect the original
return new Pair(p.getX(), p.getY());
}
public abstract void increment();
}
// synchronization of the whole method
class PairManager1 extends PairManager {
#Override
public synchronized void increment() {
p.incrementX();
p.incrementY();
}
}
// Critical section
class PairManager2 extends PairManager {
#Override
public void increment() {
synchronized (this) {
p.incrementX();
p.incrementY();
}
}
}
class PairManipulator implements Runnable {
private PairManager pairManager;
public PairManipulator(PairManager pairManager) {
this.pairManager = pairManager;
}
#Override
public void run() {
while (true)
pairManager.increment();
}
}
class PairChecker implements Runnable {
private PairManager pairManager;
public PairChecker(PairManager pairManager) {
this.pairManager = pairManager;
}
#Override
public void run() {
while (true) {
pairManager.checkCounter.incrementAndGet();
pairManager.getPair().checkState();
}
}
}
public class CriticalSection {
static void testApproaches(PairManager pman1, PairManager pman2) {
ExecutorService exec = Executors.newCachedThreadPool();
PairManipulator
pm1 = new PairManipulator(pman1),
pm2 = new PairManipulator(pman2);
PairChecker
pcheck1 = new PairChecker(pman1),
pcheck2 = new PairChecker(pman2);
exec.execute(pm1);
exec.execute(pm2);
exec.execute(pcheck1);
exec.execute(pcheck2);
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
System.out.println("InterruptedException");
}
System.out.println("pm1: " + pm1 + "\npm2: " + pm2);
System.exit(0);
}
public static void main(String[] args) {
PairManager
pman1 = new PairManager1(),
pman2 = new PairManager2();
testApproaches(pman1, pman2);
}
}
An example output:
pm1: Pair: Pair{x=364, y=364} counter = 471421
pm2: Pair: Pair{x=365, y=365} counter = 1015604598
This example executed without exception.
In above example I understand how does it work but the problem is in example with explicit locks.
Example with explicit lock from book:
class ExplicitPairManager1 extends PairManager {
private Lock lock = new ReentrantLock();
// why synchronized ??
public synchronized void increment() {
lock.lock();
try {
p.incrementX();
p.incrementY();
} finally {
lock.unlock();
}
}
}
class ExplicitPairManager2 extends PairManager {
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
p.incrementX();
p.incrementY();
} finally {
lock.unlock();
}
}
}
public class ExplicitCriticalSection {
public static void main(String[] args) throws Exception {
PairManager
pm1 = new ExplicitPairManager1(),
pm2 = new ExplicitPairManager2();
CriticalSection.testApproaches(pm1, pm2);
}
}
Output:
Exception in thread "pool-1-thread-4" critical.sections.Pair$PairValuesNotEqualException: Values are not equal: Pair{x=2, y=1}
at critical.sections.Pair.checkState(CriticalSection.java:49)
at critical.sections.PairChecker.run(CriticalSection.java:133)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
pm1: Pair: Pair{x=1024, y=1024} counter = 3
pm2: Pair: Pair{x=1025, y=1025} counter = 1499445
First what I don't understand why author use synchronized in ExplicitPairManager1#increment if he use also Lock object? Is that the mistake in the book?
Second problem is that I don't understand why I got exception?
Excpetion was thrown in:
class PairChecker implements Runnable {
private PairManager pairManager;
public PairChecker(PairManager pairManager) {
this.pairManager = pairManager;
}
#Override
public void run() {
while (true) {
pairManager.checkCounter.incrementAndGet();
pairManager.getPair().checkState(); // here was thrown an exception
}
}
}
Why I got excpetions and author dont? Is that possible JVM behavior is different on different systems? I use Ubuntu 16.04 LTS and Java 8.
You need to synchronize on the same object if you want to establish a critical section for multiple threads.
Your exception is getting thrown for pair modified in ExplicitPairManager2.
Let's see how possible exception-causing flow looks like:
ExplicitPairManager2.lock.lock() gets acquired
ExplicitPairManager2.p.incrementX() happens
PairChecker calls getPair()
PairChecker acquires pairManager's internal (this) monitor, but it is different than ExplicitPairManager2.lock
the result of getPair() therefore has x != y
so in the end there is no critical section.
In other words, while modifying, you were using two different objects to synchronize:
ExplicitPairManager2.lock to write
internal monitor of ExplicitPairManager2 (this) to create a copy for checking state

How to get/return an Integer Array from a Runnable run() method, having a while loop?

I have a Class Looper that returns an Integer array as follow:
public class Looper implements Runnable{
public AtomicBoolean keepRunning;
public Looper() {
keepRunning = new AtomicBoolean(true);
}
public void stop() {
keepRunning.set(false);
}
#Override
public void run() {
try {
.
.
.
while (keepRunning.get()) {
int[] A = ..... ;
}
}
}
int[] A will have a different values after every while loop iteration.
Now say there is another method in the same class as saveReturnValue which will store the integer array after every execution of while loop and perform some operations on it.
But due to void nature of Runnable, I am unable to get value of A in the other methods.
Is there any way to access int[] A outside of this method?
As pointed out in the comments, you can google for "Java Producer Consumer Queue example" and then fix that code to your needs.
General idea is to use a datastructure from which one thread is reading and other is writing, like below.
public class Producer implements Runnable{
private LinkedBlockingQueue<int[]> queue;
public Producer(LinkedBlockingQueue<int[]> queue) { this.queue = queue;}
#Override
public void run() {
while (keepRunning.get()) {
int[] a = ..... ;
queue.add(a);
}
}
public class Consumer implements Runnable{
private LinkedBlockingQueue<int[]> queue;
public Consumer(LinkedBlockingQueue<int[]> queue) { this.queue = queue;}
#Override
public void run() {
while (keepRunning.get()) {
int[] a = queue.take(a);
saveValue(a);
}
}
public class MainOrWhatever {
public void whateverMethod {
LinkedBlockingQueue<int[]> theQueue = new LinkedBlockingQueue<int[]>();
Consumer consumer = new Consumer(queue);
Producer producer = new Producer(queue);
executorService.submit(consumer);
executorService.submit(producer);
...
}
}

How to watch my Thread variable from Main class?

I have that code:
Main class:
public class myTest {
public static void main(String[] args) {
try {
Thread t1 = new myThreadClass("thread 1");
t1.start();
} catch (UnknownHostException ex) {
Logger.getLogger(glownyTest.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(glownyTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
My Thread class
public class myThreadClass extends Thread {
private HashSet<String> texts = new HashSet<String>();
public myThreadClass(String id) throws UnknownHostException, IOException {}
#Override
public void run() {
... collecting Strings into my hashSet ....
}
public HashSet<String> getTexts() {
return texts;
}
}
My Thread class is watching for network traffic, so I just cant call once
t1.getTexts()
whenever I want, because my hashSet can be empty (there are delays and latency in this network). How can I watch this texts hashSet and when some String will be added into hashSet - I i want my MAIN CLASS know about it? I just want to watch my Thread resources from Main class in smart way :)
If it will still be empty after my thread timeout, I want to know about it too.
You can use condition variables for this. Try something like:
class Monitor {
private final ConcurrentMap<String,String> data = new ConcurrentHashMap<String,String>();
private final Object mutex = new Object();
/* Private to the monitoring thread. Wakes up other
* threads, which may be waiting for data to arrive
*/
public void addElement(String key) {
data.put(key, key);
synchronized (mutex) { mutex.notifyAll(); }
}
public void removeElement(String key) {
data.remove(key);
synchronized (mutex) { mutex.notifyAll(); }
}
public Set<String> getElements() {
return data.keySet();
}
/* Can be called from any thread. Will wait at most "timeout"
* milliseconds
*/
public boolean waitForChanges(long timeout) throws InterruptedException {
final long then = System.currentTimeMillis() + timeout;
long left = timeout;
synchronized (mutex) {
while (data.isEmpty() && left > 0) {
mutex.wait(left);
left = then - System.currentTimeMillis();
}
return !data.isEmpty();
}
}
}
class MonitoringTask extends Runnable {
private final Monitor monitor;
MonitoringTask(Monitor m) {
this.monitor = m;
}
public void run() {
while (true) {
if (somethingHasHappened()) {
monitor.addElement("foo");
}
}
}
}
class Main {
public static void main(String[] args) {
final Monitor monitor = new Monitor();
final MonitoringTask task = new MonitoringTask(monitor);
final Thread thread = new Thread(task);
thread.setName("Monitor Thread");
thread.start();
if (monitor.waitForChanges(1500)) {
final Set<String> elts = monitor.getElements();
...
} else {
// Time-out
}
}
}
(I haven't tried to present this to a Java compiler, so watch out for all kinds of mistakes).

Categories