I run the code in IntelliJ IDEA and it would not stop. I use exec.shutdownNow() instead and it stops successfully. So, I think is the problem of generator, but I can't figure out what problem it is.
The main method:
public static void main(String[] args) {
PrimeProducer generator = new PrimeProducer(new ArrayBlockingQueue<>(10));
ExecutorService exec = Executors.newFixedThreadPool(1);
exec.execute(generator);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
generator.cancel();
}
//generator.get();
exec.shutdown();
}
And the PrimeProducer class:
public class PrimeProducer extends Thread{
private final BlockingQueue<BigInteger> queue;
PrimeProducer(BlockingQueue<BigInteger> queue){
this.queue = queue;
}
#Override
public void run() {
try {
BigInteger p = BigInteger.ONE;
while(!Thread.currentThread().isInterrupted()){
queue.put(p = p.nextProbablePrime());
}
} catch (InterruptedException e) {
}
}
public void cancel(){interrupt();}
public void get(){
for(BigInteger i : queue){
System.out.println(i.toString());
}
}
}
The latest version that still can't work:
public class PrimeProducer implements Runnable {
private final BlockingQueue<BigInteger> queue;
PrimeProducer(BlockingQueue<BigInteger> queue){
this.queue = queue;
}
#Override
public void run() {
try {
BigInteger p = BigInteger.ONE;
while(!Thread.currentThread().isInterrupted()){
queue.put(p = p.nextProbablePrime());
}
} catch (InterruptedException e) {
}
}
public void cancel(){Thread.currentThread().interrupt();}
public synchronized void get(){
for(BigInteger i : queue){
System.out.println(i.toString());
}
}
}
You have PrimeProducer extend Thread, but you don't actually use it as a thread, you only use it as a Runnable, which is executed on a thread of the thread pool. The cancel has no effect, because it calls the interrupt() of a different thread than the one that is actually running. When you then call exec.shutdown(), the thread pool will interrupt its threads to signal them they should end, when then means PrimeProducer.run will stop.
Instead, use a volatile boolean to end your run (and implement Runnable instead of extending Thread):
public class PrimeProducer implements Runnable {
private final BlockingQueue<BigInteger> queue;
private volatile boolean cancelled;
PrimeProducer(BlockingQueue<BigInteger> queue) {
this.queue = queue;
}
#Override
public void run() {
try {
BigInteger p = BigInteger.ONE;
while (!cancelled) {
queue.put(p = p.nextProbablePrime());
}
} catch (InterruptedException e) {
}
}
public void cancel() {
cancelled = true;
}
public void get() {
for (BigInteger i : queue) {
System.out.println(i.toString());
}
}
}
Related
I have this code:
public class UsbDrive extends HardDrive {
private Date lastUpdate;
private void updateDate() {
lastUpdate = new Date();
}
public synchronized void cutAndPaste(UsbDrive other, int originAddress, int destAddress) {
byte[] data = read(originAddress);
boolean success = other.write(data, destAddress);
if (success) {
erase(originAddress);
updateDate();
} else {
throw new RuntimeException("Write failed!");
}
}
}
class HardDrive {
...
public synchronized byte[] read(int address) {...}
public synchronized boolean write(byte[] data, int address) {...}
public synchronized void erase(int address) {...}
...
I'm trying to simulate a deadlock
public class Main {
private static UsbDrive usb1 = new UsbDrive();
private static UsbDrive usb2 = new UsbDrive();
public static void main(String[] args) throws Exception {
Thread thread1 = new Thread(new ThreadA());
Thread thread2 = new Thread(new ThreadB());
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
static class ThreadA implements Runnable {
#Override
public void run() {
try {
Thread.sleep(5000);
}
catch (Exception e) {
e.printStackTrace();
}
synchronized (usb1) {
usb1.cutAndPaste(usb2, 1, 2);
}
}
}
static class ThreadB implements Runnable {
#Override
public void run() {
synchronized (usb2) {
usb2.cutAndPaste(usb1, 1, 2);
}
}
}
}
However deadlock doesn't happen - why? ThreadA calls method cutAndPaste() locked on usb1, while inside that method write() is called which is locked on usb2
Shouldn't deadlock occur?
How should I change the code to trigger deadlock?
I get this output:
reading data
Erasing data
reading data
Erasing data
It is a race condition that decides whether the deadlock happens or not as far as I can see, one good option to make the deadlock more likely to happen is a loop, but an easier option might be to insert Thread.sleep(5000); between byte[] data = read(originAddress); and boolean success = other.write(data, destAddress); in UsbDrive::cutAndPaste. EDIT: And remove the existing Thread.sleep(5000);.
EDIT: Clarified answer.
EDIT2: I just ran the code with the changes, and it indeed induces a deadlock now:
import java.util.Date;
public class Main {
private static UsbDrive usb1 = new UsbDrive();
private static UsbDrive usb2 = new UsbDrive();
public static void main(String[] args) throws Exception {
Thread thread1 = new Thread(new ThreadA());
Thread thread2 = new Thread(new ThreadB());
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
static class ThreadA implements Runnable {
#Override
public void run() {
synchronized (usb1) {
usb1.cutAndPaste(usb2, 1, 2);
}
}
}
static class ThreadB implements Runnable {
#Override
public void run() {
synchronized (usb2) {
usb2.cutAndPaste(usb1, 1, 2);
}
}
}
}
class UsbDrive extends HardDrive {
private Date lastUpdate;
private void updateDate() {
lastUpdate = new Date();
}
public synchronized void cutAndPaste(UsbDrive other, int originAddress, int destAddress) {
byte[] data = read(originAddress);
try {
Thread.sleep(5000);
}
catch (Exception e) {
e.printStackTrace();
}
boolean success = other.write(data, destAddress);
if (success) {
erase(originAddress);
updateDate();
} else {
throw new RuntimeException("Write failed!");
}
}
}
class HardDrive {
public synchronized byte[] read(int address) {return new byte[]{};}
public synchronized boolean write(byte[] data, int address) {return true;}
public synchronized void erase(int address) {}
}
I am new to Java Concurrency and trying to achieve/implement Single Producer[P1] and Multiple Consumer [C1,C2,C3].
The idea is producer [P1] puts in the value and consumers C1,C2,C3 all runs their task to read the value individually as put in by P1. Once C1,C2,C3 reads the values, P1 again puts a new data. Then C1,C2,C3 reads data and this loop goes on.
Wait Notify works fine for Single Producer Single Consumer, but in this case of Single Producer Multiple Consumer wait notify concept doesn't look to be good strategy. How should I approach this problem.
Thanks to #Ivan and #Andreas.
#Ivan - In his comment made me understand how Producer Consumer pattern behaves.
#Andreas - In his Comment suggested the usage of Phaser. (I used Cyclic Barrier instead since my number of registered threads does not vary dynamically)
With both their comments sharing the below sample code.
Please do suggest improvisation if there any or a better way to handle this.
Main Class
public static void main(String[] args)
{
SharedSpace sharedSpace = new SharedSpace(new LinkedBlockingQueue<Integer>(1));
new Thread(new Producer(sharedSpace)).start();
Consumer consumerRunnable = new Consumer(sharedSpace);
new Thread(consumerRunnable).start();
CyclicBarrier barrier = new CyclicBarrier(3,consumerRunnable);
new Thread(new EndUser(barrier,consumerRunnable)).start();
new Thread(new EndUser(barrier,consumerRunnable)).start();
new Thread(new EndUser(barrier,consumerRunnable)).start();
}
Producer
private SharedSpace sharedSpace;
public Producer(SharedSpace sharedSpace) {
super();
this.sharedSpace = sharedSpace;
}
public SharedSpace getSharedSpace() {
return sharedSpace;
}
public void setSharedSpace(SharedSpace sharedSpace) {
this.sharedSpace = sharedSpace;
}
#Override
public void run() {
for(int i=0;i<3;i++)
{
int value = (int) (Math.random()*30);
sharedSpace.addValue(value);
}
}
Queue Shared by Producer and Consumer
private BlockingQueue<Integer> queue;
public SharedSpace(BlockingQueue<Integer> queue) {
super();
this.queue = queue;
}
public BlockingQueue<Integer> getQueue() {
return queue;
}
public void setQueue(BlockingQueue<Integer> queue) {
this.queue = queue;
}
public void addValue(int value)
{
try {
queue.put(value);
System.out.println(System.nanoTime()+" Producer added value "+value);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public int getValue() throws InterruptedException
{
return queue.take();
}
Consumer
private SharedSpace sharedSpace;
private Integer value;
public Consumer(SharedSpace sharedSpace) {
super();
this.sharedSpace = sharedSpace;
}
public SharedSpace getSharedSpace() {
return sharedSpace;
}
public void setSharedSpace(SharedSpace sharedSpace) {
this.sharedSpace = sharedSpace;
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
#Override
public void run()
{
try {
setValue(sharedSpace.getValue());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
EndUser
CyclicBarrier barrier;
Consumer consumer;
public EndUser(CyclicBarrier barrier) {
super();
this.barrier = barrier;
}
public EndUser(CyclicBarrier barrier, Consumer consumer) {
super();
this.barrier = barrier;
this.consumer = consumer;
}
public Consumer getConsumer() {
return consumer;
}
public void setConsumer(Consumer consumer) {
this.consumer = consumer;
}
public CyclicBarrier getBarrier() {
return barrier;
}
public void setBarrier(CyclicBarrier barrier) {
this.barrier = barrier;
}
#Override
public void run() {
try
{
while(true)
{
System.out.println(consumer.getValue());
barrier.await();
}
}
catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
Output [Consumer doesn't read from Producer unless all EndUser has taken their Data]
Producer added value 24
Producer added value 10
24
24
24
10
10
Producer added value 0
10
0
0
0
DefaultRunners are producers
and OrderTaker is a consumer
They both share a OrderQueue.
Currently, I use the variable isDone to indicate if a game is finished.
Once each round is done, I want to make it repeat again and again.
However, in my current implementation it will only run once.
How could I solve it?
public class OrderQueue {
public synchronized void pushOrder(Order order) throws InterruptedException {
if (isDone) {
wait();
} else {
runnersQueue.addLast(order);
notifyAll();
}
}
public void pullOrder() {
try {
if (runnersQueue.size() == 0) {
} else if (isDone) {
wait();
} else {
handleOrder(runnersQueue.pop());
}
} catch (InterruptedException e) {
}
}
In my main class
while(true){
enterYesToStart();
DefaultRunners dfltRunner = new DefaultRunners(queue);
OrderTaker taker = new OrderTaker(queue);
taker.run();
System.out.println("This round is finished"); # never reach to this line
}
Here's the full source code for the example
https://gist.github.com/poc7667/d98e3bf5b3b470fcb51e00d9a0d80931
I've taken a look at your code snippets and the problem is fairly obvious.
The main thread runs the OrderTaker runnable. The main thread is stuck in an eternal loop as the while statement cannot complete unless it throws an exception. (Note that the same is true for your ThreadRunner runnable.)
This means that the main thread i still pulling orders while the race is already done.
The OrderTaker should exit it's while loop while once the race is done. I guess that there are multiple ways achieve this, but one way is use a shared variable.
I took your code and adapted it into a working example.
import java.util.*;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class RaceApp {
public static void main(String[] args) throws InterruptedException {
final RaceUpdateManager queue = new RaceUpdateManager();
for (int i = 0; i < 3; i++) {
queue.reset();
List<Thread> threads = Arrays.asList(
new Thread(new Runner("Tortoise", 0, 10, queue)),
new Thread(new Runner("Hare", 90, 100, queue))
);
for (Thread thread : threads) {
thread.start();
}
RaceUpdatesProcessor processor = new RaceUpdatesProcessor(queue);
processor.run();
System.out.println("Game finished");
}
}
private static class RaceUpdateManager {
private static final int TOTAL_DISTANCE = 300;
//thread-safe implementation for queue so no external syncrhonization is required when adding/removing updates
private final Deque<RaceUpdate> runnersQueue = new ConcurrentLinkedDeque<>();
//lock used to sync changes to runnersRecords and done variables
private final ReadWriteLock raceStatusLock = new ReentrantReadWriteLock();
private final Map<String, Integer> runnersRecords = new HashMap<>();
private volatile boolean raceDone = false;//volatile keyword guarantees visibility of changes to variables across threads
public boolean isRaceDone() {
return raceDone;
}
//updates can by added simultaneously (read lock)
public void register(RaceUpdate raceUpdate) throws InterruptedException {
Lock readLock = raceStatusLock.readLock();
readLock.lock();
try {
if (!raceDone) {
runnersQueue.addLast(raceUpdate);
}//ignore updates when the race is done
} finally {
readLock.unlock();
}
}
//but they need to be processed in order (exclusive write lock)
public void processOldestUpdate() {
Lock writeLock = raceStatusLock.writeLock();
writeLock.lock();
try {
RaceUpdate raceUpdate = runnersQueue.poll();
if (raceUpdate != null) {
handleUpdate(raceUpdate);
}
} finally {
writeLock.unlock();
}
}
private void handleUpdate(RaceUpdate raceUpdate) {
Integer distanceRun = runnersRecords.merge(
raceUpdate.runner, raceUpdate.distanceRunSinceLastUpdate, (total, increment) -> total + increment
);
System.out.printf("%s: %d\n", raceUpdate.runner, distanceRun);
if (distanceRun >= TOTAL_DISTANCE) {
raceDone = true;
System.out.printf("Winner %s\n", raceUpdate.runner);
}
}
public void reset() {
Lock writeLock = raceStatusLock.writeLock();
writeLock.lock();
try {
runnersQueue.clear();
runnersRecords.clear();
raceDone = false;
} finally {
writeLock.unlock();
}
}
}
public static class Runner implements Runnable {
private final String name;
private final int rest;
private final int speed;
private final RaceUpdateManager queue;
private final Random rand = new Random();
public Runner(String name, int rest, int speed, RaceUpdateManager queue) {
this.name = name;
this.rest = rest;
this.speed = speed;
this.queue = queue;
}
#Override
public void run() {
while (!queue.isRaceDone()) {
try {
if (!takeRest()) {
queue.register(new RaceUpdate(this.name, this.speed));
}
Thread.sleep(100);
} catch (InterruptedException e) {
//signal that thread was interrupted and exit method
Thread.currentThread().interrupt();
return;
}
}
}
private boolean takeRest() {
return rand.nextInt(100) < rest;
}
}
public static class RaceUpdatesProcessor implements Runnable {
private final RaceUpdateManager queue;
public RaceUpdatesProcessor(RaceUpdateManager queue) {
this.queue = queue;
}
#Override
public void run() {
while (!queue.isRaceDone()) {
try {
queue.processOldestUpdate();
Thread.sleep(50);
} catch (InterruptedException e) {
//signal that thread was interrupted and exit method
Thread.currentThread().interrupt();
return;
}
}
}
}
public static class RaceUpdate {
public final String runner;
public final int distanceRunSinceLastUpdate;
public RaceUpdate(String runner, int distanceRunSinceLastUpdate) {
this.runner = runner;
this.distanceRunSinceLastUpdate = distanceRunSinceLastUpdate;
}
}
}
I have a fixed pool with a single thread. When I submit new task I want to stop all old threads except last one.
private class MyPool extends ThreadPoolExecutor {
public MyPool(long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
super(1, 1, keepAliveTime, unit, workQueue);
}
public boolean isReady() {
return semaphore;
}
#Override
public <T> Future<T> submit(Callable<T> task) {
// Iterate all existed task and stop
Future<T> future = super.submit(task);
return future;
}
private volatile boolean semaphore;
}
Code of running task:
private class MyTask implements Runnable {
private volatile boolean isRun = true;
private int id;
public MyTask(int id) {
this.id = id;
}
public void stop() {
isRun = false;
}
#Override
public void run() {
try {
System.out.println("Start " + id);
if (isRun) {
Thread.sleep(1000);
System.out.println("Stop " + id);
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
I created my own class, but It doesn't correctly work because semaphore effects on a new task as well. What is the best way to do it?
This ThreadPoolExecutor kills the running thread if a new Callable is submitted:
class MyPool extends ThreadPoolExecutor {
private volatile Thread activeThread = null;
private static final Field FutureTask$runner;
static {
try {
FutureTask$runner = FutureTask.class.getDeclaredField("runner");
FutureTask$runner.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new Error(e);
}
}
private static Thread getThread(FutureTask<?> task) {
try {
return (Thread) FutureTask$runner.get(task);
} catch (IllegalAccessException e) {
throw new Error(e);
}
}
public MyPool() {
super(1, 1,
//whatever here
5000, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>());
}
#Override
public <T> Future<T> submit(Callable<T> task) {
if(activeThread != null) {
activeThread.stop(); //kill
}
FutureTask<T> activeTask = (FutureTask<T>)super.submit(task);
activeThread = getThread(activeTask); //steal thread reference for killing
return activeTask;
}
}
I am having a trouble to share a resource with three threads...
public class Subject{
int i;
boolean valueSet1 = false;
boolean valueSet2 = true;
boolean valueSet3 = true;
void put(int i){
while(valueSet1){
try{
wait();
}catch(InterruptedException e){
System.out.println("Producer thread interrupted");
}
}
System.out.println("Producer thread wakesup");
valueSet1=true;
valueSet2=false;
this.i=i;
System.out.println("Put: "+i);
notify();
}
void makesquare(){
int a;
while(valueSet2){
try{
System.out.println("Convertor thread goin to sleep");
wait();
}catch(InterruptedException e){
System.out.println("Convertor thread interrupted");
}
}
System.out.println("Convertor thread wakesup");
valueSet2 = true;
valueSet3=false;
a = this.i;
this.i = a*a;
System.out.println("Made: "+i);
notify();
}
void get(){
while(valueSet3){
try{
System.out.println("Consumer thread goin to sleep");
wait();
}catch(InterruptedException e){
System.out.println("Consumer thread interrupted");
}
}
System.out.println("Consumer thread wakesup");
valueSet3 = true;
valueSet1 = false;
System.out.println("Got: "+i);
notify();
}
}
class Producer implements Runnable{
Subject q;
Thread t;
String msg;
Producer(Subject q, String msg){
this.q=q;
this.msg = msg;
t = new Thread(this, this.msg);
}
#Override
public void run(){
int i=2;
while(true){
synchronized(q){
q.put(i++);
}
}
}
}
class Consumer implements Runnable{
Subject q;
Thread t;
String msg;
Consumer(Subject q,String msg){
this.q = q;
this.msg = msg;
t = new Thread(this, this.msg);
}
#Override
public void run(){
while(true){
synchronized(q){
q.get();
}
}
}
}
class Convertor implements Runnable{
Subject q;
Thread t;
String msg;
Convertor(Subject q, String msg){
this.q=q;
this.msg = msg;
t = new Thread(this, this.msg);
}
#Override
public void run(){
while(true){
synchronized(q){
q.makesquare();
}
}
}
}
There are three threads in the program. One thread produces while another makes square of the produced quantity. While the last thread consumes the squared product.They all share the same object.
public class Thread3way {
public static void main(String[] args) {
Subject q = new Subject();
Producer P = new Producer(q, "producer");
Convertor Cv = new Convertor(q, "convertor");
Consumer Cs = new Consumer(q, "consumer");
P.t.start();
Cv.t.start();
Cs.t.start();
}
}
Your wait loop is not quite correct, you need to keep looping until your condition is true before you do any modifications. I'd do it like this (using a State enum to make things clearer):
public class Subject {
static enum State { EMPTY, WAITING_TO_SQUARE, WAITING_TO_GET };
State state;
int value;
public synchronized void put(int i) {
while (state != State.EMPTY) {
try {
wait();
}catch(InterruptedException e) {
System.out.println("Put interrupted");
}
}
value = i;
state = State.WAITING_TO_SQUARE;
}
}
As a commenter pointed out, you don't need to synchronize twice, either synchronized(q) around the Subject calls, or declare your methods synchronized. You don't need both.
No need to use Runnables explicitly, just make Producer, Convertor, and Consumer Threads directly. Then you don't need the t fields, and you can start the threads like P.start().
Sounds to me like you're doing some kind of pipeline with 3 stages. Why not enjoy the benefits of ExecutorService:
class ConvertorTask implements Runnable {
private int number;
private static ExecutorService consumer = Executors.newSingleThreadExecutor();
public ConvertorTask(int number) {
this.number = number;
}
public void run() {
consumer.submit(new ConsumerTask(number * number));
}
}
class ConsumerTask implements Runnable {
private int number;
public ConsumerTask(int number) {
this.number = number;
}
public void run() {
System.out.println(number);
}
}
class Producer implements Runnable {
private ExecutorService convertor = Executors.newSingleThreadExecutor();
public void run() {
int i = 0;
while(true) {
convertor.submit(new ConvertorTask(i++));
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new Producer());
t.start();
}
}