I have thread class that is initialized with an AtomicBoolean (set to true).
public class WThread implements Runnable {
private Socket _listenerSocket;
private BufferedReader _br;
private final AtomicBoolean _isRunning;
private final AtomicBoolean _isRunning;
public WThread(Socket listenerSocket, AtomicBoolean isRunning) {
_listenerSocket = listenerSocket;
_isRunning = isRunning;
}
}
public void run() {
try {
System.out.println("Starting a worker thread.");
_br = new BufferedReader(new InputStreamReader(_listenerSocket.getInputStream()));
_command = _br.readLine();
dispatchCommand(_command);
} catch (IOException e) {
}
finally {
try {
_listenerSocket.close();
} catch (IOException e) {
}
}
}
private void dispatchCommand(String _command) {
switch(_command) {
case "fail":
fail();
break;
default:
break;
}
}
private void fail() {
System.out.println("Failed node.");
_isRunning.set(false);
try {
_listenerSocket.close();
} catch (IOException e) {
}
}
Later on, in the same class, I set that boolean to false...
_isRunning.set(false);
For some reason, it seems like the reference is not working and that the original AtomicBoolean is never set, since some expected actions don't occur in parent threads.
Here's the parent class, which fails to print the "fail":
public class ParentThread implements Runnable {
private ExecutorService _executor = null;
private final AtomicBoolean _isRunning = null;
public ParentThread(ExecutorService executor, AtomicBoolean isRunning)(
_executor = executor;
_isRunning = isRunning;
}
public void run() {
try {
while(_isRunning.get()) {
_executor.submit(new WThread(_isRunning));
}
if (!_isRunning.get()) {
System.out.println("Fail.");
_executor.shutdownNow();
}
} catch (IOException e) {
}
}
}
Related
I am learning multithreading. I am implementing producer and consumer problem. I am stuck on scenario where i want that when I press anything apart from integer from keyboard, all my threads should die and there is no memory in use by threads. Please have your valuable inputs to help me achieve it. Below is all the code I am using.
package com.java.concurrency;
public class ThreadSignaling {
private int i = -1;
private boolean valueSet = false;
private boolean stopFlag = false;
public void put(int value) {
synchronized (this) {
while (valueSet) {
if (stopFlag) {
System.out.println("Byeeeeeeeeeeeee");
break;
}
try {
this.wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException while waiting in put() : " + e);
}
}
this.i = value;
this.valueSet = true;
System.out.println("Value put : " + this.i);
this.notify();
}
}
public void get() {
synchronized (this) {
while (!valueSet) {
if (stopFlag) {
System.out.println("Byeeeeeeeeeeeee");
break;
}
try {
this.wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException while waiting in get() : " + e);
}
}
System.out.println("Value get : " + this.i);
valueSet = false;
this.notify();
}
}
public void finish() {
synchronized (this) {
stopFlag = true;
this.notifyAll();
}
}
}
public class Producer implements Runnable {
private ThreadSignaling sharedObj = null;
private final Scanner input = new Scanner(System.in);
public Producer(ThreadSignaling obj) {
this.sharedObj = obj;
}
#Override
public void run() {
int value = -1;
System.out.println("Press Ctrl-c to stop... ");
while (true) {
System.out.println("Enter any integer value : ");
if (input.hasNextInt()) {
value = input.nextInt();
} else {
this.sharedObj.finish();
return;
}
this.sharedObj.put(value);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("InterruptedException while sleeping" + e);
}
}
}
}
public class Consumer implements Runnable {
private ThreadSignaling sharedObj = null;
public Consumer(ThreadSignaling obj) {
this.sharedObj = obj;
}
#Override
public void run() {
while (true) {
this.sharedObj.get();
}
}
}
public class MainThread {
public static void main(String[] args) {
ThreadSignaling sharedObj = new ThreadSignaling();
Producer in = new Producer(sharedObj);
Consumer out = new Consumer(sharedObj);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
} enter code here
The problem with your code is that you do not have an exit condition for the Consumer. The run() method of the Consumer will run forever, and while doing repeated get calls on the shared object.
What you need to do is to make aware the Consumer that the Producer has set the stopFlag in the shared object. And if that stopFlag is true then the loop in the Consumer should also finish. There are several ways you can do that:
redefine get method to return the value of stopFlag;
define a new method to return just the value of stopFlag;
In either cases, make a test in the Consumer.run() and if the value is true, just do a return so the infinite loop ends.
let's say i have 3 classes:
1. Storage which contains just one integer.
2. Counter which contains a thread inside who's responsible for counting (0,1,..,k) and stores each iteration of the loop index in Storage class.
3.Printer which contains a thread who's responsible for reading the value in class Storage and print it.
now i have to create a main class which creates these 3 objects runs the threads of Counter and Printer , and everynumber from(0,1,..,k) has to be printed just once and in the right order.
how do i synchronize the access to my Storage class so first i put a number inside Storage with Counter ,than print it with my Printer class ?
here's what i've wrote so far:
public class Storage {
private int num;
public Storage(){
}
public synchronized void setNum(int num){
this.num = num;
}
public synchronized int getNum(){
return num;
}
public class Counter implements Runnable {
Storage s;
public Counter(Storage t){
s = t;
}
#Override
public void run() {
int i = 0;
while(true){
s.setNum(i++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Printer implements Runnable {
Storage s;
public Printer(Storage s){
this.s= s;
}
#Override
public void run() {
while(true){
System.out.println(s.getNum());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class mainProg {
public static void main(String[] args){
Storage s = new Storage();
Counter c = new Counter(s);
Printer p = new Printer(s);
Thread c1 = new Thread(c);
Thread p2 = new Thread(p);
c1.start();
p2.start();
}
}
EDIT: i found out a solution, here it is:
public class Storage {
private int num;
private boolean available = false;
public Storage(){
}
public synchronized void setNum(int num){
while(available){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
available = true;
notifyAll();
this.num = num;
}
public synchronized int getNum(){
while(!available){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
available = false;
notifyAll();
return num;
}
}
This approach won't work, because it's not guaranteed that for every cycle of Counter a cycle of Printer will be executed in a parallel thread. You need to be able to store more than a one value in your Storage.
You can use BlockingQueue here and rewrite your Storage class like this:
public class Storage {
private BlockingQueue<Integer> numbers = new LinkedBlockingQueue<Integer>();
public void setNum(int num) {
try {
this.numbers.put(num);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public int getNum() {
try {
return numbers.take();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
Note that if BlockingQueue is empty and Printer wants to get a new value, it will wait while a new element occurrs in the queue.
I've written out my code signalling north and southbound cars crossing a one lane bridge but I'm having some trouble with counting.
It should read like: a car is waiting, then maybe several, with one crossing at a time and increasing every time. Instead it repeats the same three numbers every time.
Should I declare my count int differently or am I increasing it incorrectly? I've tried many different ways and can't quite find the true issue.
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SingleLaneBridge {
public static void main(String[] args) {
final Bridge bridge = new Bridge();
Thread th1 = new Thread( new Runnable() {
#Override
public void run() {
while(true) {
Car car = new Car(bridge);
Thread th = new Thread(car);
th.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
Thread th2 = new Thread( new Runnable() {
#Override
public void run() {
while(true) {
Car car = new Car(bridge);
Thread th = new Thread(car);
th.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
th1.start();
th2.start();
}
}
class Bridge {
private final Semaphore semaphore;
public Bridge() {
semaphore = new Semaphore(1);
}
public void crossBridge(Car car) {
try {
System.out.printf("Car %s is trying to cross the bridge. \n",car.count++);
semaphore.acquire();
System.out.printf("Car %s is crossing the bridge. \n",car.count++);
Thread.sleep(5000);
} catch(InterruptedException iex) {
iex.printStackTrace();
} finally {
System.out.printf(" Car %s has crossed the bridge. \n",car.count++);
semaphore.release();
}
}
}
class Car implements Runnable {
int count = 0;
private String name;
private Bridge bridge;
public Car(Bridge bridge) {
this.bridge = bridge;
}
public void run() {
bridge.crossBridge(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The reason why it repeats the three numbers again and again is that, the Car instances are created afresh every time and the count is initialized to 0.
To overcome this, define the Car class as follows to get the atomic counting as multiple Threads (Cars) are involved here,
class Car implements Runnable {
private static AtomicInteger globalCarID = new AtomicInteger(0);
int count;
...
public Car(Bridge bridge) {
this.bridge = bridge;
count = globalCarID.incrementAndGet();
}
}
And modify the System.out.printf's in crossBridge() method to not to increment the count,
Below is the complete code that might serve what you wanted,
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class SingleLaneBridge {
public static void main(String[] args) {
final Bridge bridge = new Bridge();
Thread th1 = new Thread( new Runnable() {
public void run() {
while(true) {
Car car = new Car(bridge);
Thread th = new Thread(car);
th.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
Thread th2 = new Thread( new Runnable() {
public void run() {
while(true) {
Car car = new Car(bridge);
Thread th = new Thread(car);
th.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
th1.start();
th2.start();
}
}
class Bridge {
private final Semaphore semaphore;
public Bridge() {
semaphore = new Semaphore(1);
}
public void crossBridge(Car car) {
try {
System.out.printf("Car %s is trying to cross the bridge. \n",car.count);
semaphore.acquire();
System.out.printf("Car %s is crossing the bridge. \n",car.count);
Thread.sleep(500);
} catch(InterruptedException iex) {
iex.printStackTrace();
} finally {
System.out.printf(" Car %s has crossed the bridge. \n",car.count);
semaphore.release();
}
}
}
class Car implements Runnable {
private static AtomicInteger globalCarID = new AtomicInteger(0);
int count;
private String name;
private Bridge bridge;
public Car(Bridge bridge) {
this.bridge = bridge;
count = globalCarID.incrementAndGet();
}
public void run() {
bridge.crossBridge(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I'm learning concurrency and made some naive program to play with ExecutorService and Future tasks.
Also I want to check why instanceof is bad in some cases.
public class Test {
static enum Some {
FOO;
}
static abstract class Foo {
public abstract Some getType();
}
static class FooExt extends Foo {
public Some getType() {
return Some.FOO;
}
}
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(2);
final CountDownLatch start = new CountDownLatch(1);
Future<Integer> f1 = service.submit(new Callable<Integer>() {
#Override
public Integer call() {
try {
start.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task started...");
int a = 0;
Foo foo = new FooExt();
while (!Thread.currentThread().isInterrupted()) {
if (foo instanceof FooExt) {
a++;
}
}
System.out.println("Task ended...");
return a;
}
});
Future<Integer> f2 = service.submit(new Callable<Integer>() {
#Override
public Integer call() {
try {
start.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task started...");
int a = 0;
Foo foo = new FooExt();
while (!Thread.currentThread().isInterrupted()) {
if (foo.getType() == Some.FOO) {
a++;
}
}
System.out.println("Task ended...");
return a;
}
});
start.countDown();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
service.shutdownNow();
System.out.println("service is shutdowned...");
try {
System.out.println("instanceof: "+f1.get());
System.out.println("enum: "+f2.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
but unfortunately my code is never terminated, and I cant get any values from my tasks :(
Hi I have executed your program. I got the following output:
Task started...
Task started...
Task ended...
service is shutdowned...
Task ended...
instanceof: 1287184
enum: 1247375
This code terminates.
What is advantage of locks over wait/notify?
Code is very similar.
private Object full = new Object();
private Object empty = new Object();
private Object data = null;
public static void main(String[] args) {
Test test = new Test();
new Thread(test.new Producer()).start();
new Thread(test.new Consumer()).start();
}
public void push(Object d) {
synchronized (full) {
while (data != null)
try {
full.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
data = d;
System.out.println("push");
synchronized (empty) {
if (data != null)
empty.notify();
}
}
public Object pop() {
synchronized (empty) {
while (data == null)
try {
empty.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Object o = data;
data = null;
System.out.println("pop");
synchronized (full) {
if (data == null)
full.notify();
}
return o;
}
class Producer implements Runnable {
public void run() {
while (true) {
push(new Object());
}
}
}
class Consumer implements Runnable {
public void run() {
while (true) {
pop();
}
}
}
and
private final ReentrantLock lock = new ReentrantLock();
private final Condition fullState = lock.newCondition();
private final Condition emptyState = lock.newCondition();
private Object data = null;
public static void main(String[] args) {
Test test = new Test();
new Thread(test.new Producer()).start();
new Thread(test.new Consumer()).start();
}
public void push(Object d) {
lock.lock();
try {
while (data != null)
try {
fullState.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
data = d;
System.out.println("push");
emptyState.signal();
} finally {
lock.unlock();
}
}
public Object pop() {
Object result;
lock.lock();
try {
while (data == null)
try {
emptyState.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
result = data;
data = null;
System.out.println("pop");
fullState.signal();
} finally {
lock.unlock();
}
return result;
}
class Producer implements Runnable {
public void run() {
while (true) {
push(new Object());
}
}
}
class Consumer implements Runnable {
public void run() {
while (true) {
pop();
}
}
}
Check out the JavaDoc for ReeentratLock and your question will be answered.
"A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities."
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html