Run the Main.main() method seems like a deadlock has occurred.
I found out it can be fixed if replace notify() with notifyAll().
But why?
Shouldn't the worst case always be called Lazy Thread to another Lazy Thread?
public class Main {
public static void main(String[] args) {
Table table = new Table(3);
new MakerThread("MakerThread-1", table, 8931415L).start();
new MakerThread("MakerThread-2", table, 314144L).start();
new MakerThread("MakerThread-3", table, 42131415L).start();
new EaterThread("EaterThread-1", table, 6313L).start();
new EaterThread("EaterThread-2", table, 8536313L).start();
new EaterThread("EaterThread-3", table, 35256313L).start();
new LazyThread("LazyThread-1", table).start();
new LazyThread("LazyThread-2", table).start();
new LazyThread("LazyThread-3", table).start();
new LazyThread("LazyThread-4", table).start();
new LazyThread("LazyThread-5", table).start();
new LazyThread("LazyThread-6", table).start();
new LazyThread("LazyThread-7", table).start();
}
}
public class Table {
private final String[] buffer;
private int tail;
private int head;
private int count;
public Table(int count) {
this.buffer = new String[count];
this.tail = 0;
this.head = 0;
this.count = 0;
}
public synchronized void put(String cake) throws InterruptedException {
while (count >= buffer.length) {
wait();
}
System.out.println(Thread.currentThread().getName() + " puts " + cake);
buffer[tail] = cake;
tail = (tail + 1) % buffer.length;
count++;
notify();
}
public synchronized String take() throws InterruptedException {
while (count <= 0) {
wait();
}
String cake = buffer[head];
head = (head + 1) % buffer.length;
count--;
System.out.println(Thread.currentThread().getName() + " takes " + cake);
notify();
return cake;
}
}
public class EaterThread extends Thread {
private final Random random;
private final Table table;
public EaterThread(String name, Table table, long seed) {
super(name);
this.random = new Random(seed);
this.table = table;
}
#Override
public void run() {
try {
while (true) {
String cake = table.take();
Thread.sleep(random.nextInt(1000));
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public class MakerThread extends Thread {
private final Random random;
private final Table table;
private static int id = 0;
public MakerThread(String name, Table table, long seed) {
super(name);
this.random = new Random(seed);
this.table = table;
}
#Override
public void run() {
try {
while (true) {
Thread.sleep(random.nextInt(1000));
String cake = " Cake No." + nextId() + " by " + getName() + " ]";
table.put(cake);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
private static synchronized int nextId() {
return ++id;
}
}
public class LazyThread extends Thread {
private final Table table;
public LazyThread(String name, Table table) {
super(name);
this.table = table;
}
#Override
public void run() {
while (true) {
try {
synchronized (table) {
table.wait();
}
System.out.println(getName() + " is notified");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
Console output
You need notifyAll instead of notify. Otherwise, the a maker's notify could wake up another maker and put the whole thing into deadlock. Ditto for the lazies.
A better way to do this would be to use one lock for the makers and one lock for the lazies (takers) then you can just use notify when things are added or removed
public synchronized void put(String cake) throws InterruptedException {
while (count >= buffer.length) {
wait();
}
System.out.println(Thread.currentThread().getName() + " puts " + cake);
buffer[tail] = cake;
tail = (tail + 1) % buffer.length;
count++;
notifyAll();
}
public synchronized String take() throws InterruptedException {
while (count <= 0) {
wait();
}
String cake = buffer[head];
head = (head + 1) % buffer.length;
count--;
System.out.println(Thread.currentThread().getName() + " takes " + cake);
notifyAll();
return cake;
}
As the doc says:
public final void notify()
... If any threads are waiting on this object, one of them is chosen
to be awakened. The choice is arbitrary and occurs at the discretion
of the implementation ...
...the awakened thread enjoys no reliable privilege or disadvantage in
being the next thread to lock this object. ...
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#notify()
You can absolutely implement this so that you notify() only one thread. It depends on when the locked object is released by the preceding thread. If one thread is notified but the resource is still bound to the notifying thread, the released thread goes back to the wait status and after that there is no thread being notified.
When you notifyall() waiting threads and when the first thread does not get the locked object (because still locked by the notifying thread) then the remaining awoken threads will try to catch it.
So, with many awoken threads there is a much higher possibility of the locked object being catched by one of them.
I have a bunch of threads that spawn somewhat arbitrarily. When they are racing each other, only the one that spawned last is relevant. The other threads can be thrown away or stopped. But I am not sure how to do that, so I have implemented a very basic counter that checks whether the thread is the latest spawned thread.
edit: I would like to be able to kill threads that are taking too long (as they are no longer necessary); probably not from within the threads themselves as they are busy doing something else.
This code works, it seems. But it doesn't feel robust. Can someone give me a hint toward a proper way to do this?
class Main {
private static volatile int latestThread = 0;
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
spawnThread();
}
}
private static void spawnThread() {
latestThread++;
int thisThread = latestThread;
new Thread(() -> {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (latestThread == thisThread) {
// only the latest "active" thread is relevant
System.out.println("I am the latest thread! " + thisThread);
}
}).start();
}
}
output:
I am the latest thread! 10
code in replit.com
ThreadPoolExecutor is almost what I need, specifically DiscardOldestPolicy. You can set the queue size to 1, so one thread is running and one thread is in the queue, and the oldest in the queue just gets shunted. Clean!
But it finishes two threads (not only the latest), which is not 100% what I was looking for. Although arguably good enough:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class DiscardOldest {
private static int threadCounter = 1;
public static void main(String[] args) throws InterruptedException {
int poolSize = 0;
int maxPoolSize = 1;
int queueSize = 1;
long aliveTime = 1000;
ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(queueSize);
ThreadPoolExecutor executor = new ThreadPoolExecutor(poolSize, maxPoolSize, aliveTime, TimeUnit.MILLISECONDS, queue, new ThreadPoolExecutor.DiscardOldestPolicy());
for (int i = 0; i < 4; i++) {
spawnThread(executor);
}
}
private static void spawnThread(ThreadPoolExecutor executor) {
final int thisThread = threadCounter++;
System.out.println(thisThread + " spawning");
executor.execute(() -> {
try {
Thread.sleep(100);
System.out.println(thisThread + " finished!");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
Ouput:
1 spawning
2 spawning
3 spawning
4 spawning
1 finished!
4 finished!
Rather than relaying on an index, a born time could be set. If there's a younger thread (was born later) the thread should terminate its execution.
public class Last {
private static volatile long latestThread = 0L;
/**
* #param args
*/
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
spawnThread(System.nanoTime(), i);
}
}
private static void spawnThread(long startTime, int index) {
new Thread(() -> {
latestThread = startTime;
long thisThread = startTime;
boolean die = false;
try {
while (!die) {
Thread.sleep(1);
if (thisThread < latestThread) {
System.out.println(
index + ": I am not the latest thread :-(\n\t" + thisThread + "\n\t" + latestThread);
die = true;
} else if (thisThread == latestThread) {
System.out.println(
index + ": Yes! This is the latest thread!\n\t" + thisThread + "\n\t" + latestThread);
Thread.sleep(1);
System.out.println("Bye!");
die = true;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
Result:
0: I am not the latest thread :-(
39667589567880
39667602317461
2: Yes! This is the latest thread!
39667602317461
39667602317461
1: I am not the latest thread :-(
39667602257160
39667602317461
Bye!
I did a little research based on comments from everybody (thanks!) and ThreadPoolExecutor is almost what I need, but I want a pool with the total size of 1 (no queue) that kills the active thread once a new thread comes along, which is not allowed in a thread pool and not in line with what a ThreadPool is for. So instead, I came up with a reference to the active thread, and when a new thread comes a long it kills the old one, which seems to do what I want:
import java.util.concurrent.atomic.AtomicInteger;
public class Interrupt {
private static final AtomicInteger CURRENT_THREAD = new AtomicInteger(0);
private static Thread activeThread = new Thread(() -> {});
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 4; i++) {
spawnThread();
Thread.sleep(3);
}
}
private static void spawnThread() {
if (activeThread.isAlive()) {
activeThread.interrupt();
}
activeThread = new Thread(() -> {
int thisThread = CURRENT_THREAD.incrementAndGet();
System.out.println(thisThread + " working");
try {
Thread.sleep(1000);
System.out.println(thisThread + " finished!");
} catch (InterruptedException ignored) {}
});
activeThread.start();
}
}
Output:
3 working
2 working
1 working
4 working
4 finished!
I'm trying to solve single consumer/producer problem using monitor in Java, and the code is as follows. When I run this code, it will finally get stucked. The most typical case is that the consumer calls wait(), and then the producer keeps producing but cannot notify the consumer (although it will call notify()). I don't know why it's happening. Java code:
import java.util.*;
class Monitor {
int length;
int size;
int begin, end;
int queue[];
private static Random randGenerator;
public Monitor() {}
public Monitor(int length) {
this.length = length;
this.size = 0;
begin = end = 0;
queue = new int[length];
randGenerator = new Random(10);
}
public synchronized void produce() throws InterruptedException {
while(size == length) {
System.out.println("Producer waiting");
wait();
}
int produced = randGenerator.nextInt();
size++;
queue[end] = produced;
end = (end + 1) % length;
System.out.println("Produce element " + produced + " size "+size);
// When size is not 1, no thread is blocked and therefore don't need to notify
if(size == 1) {
System.out.println("Notify consumer");
notify();
}
}
public synchronized void consume() throws InterruptedException {
while(size == 0) {
System.out.println("Consumer waiting, size " + size);
wait();
}
size--;
System.out.println("Consume element " + queue[begin] + " size " + size);
begin = (begin + 1) % length;
if(size == length - 1) {
System.out.println("Notify producer");
notify();
}
}
}
class Producer implements Runnable {
Monitor producer;
public Producer(Monitor m) {
producer = m;
}
#Override
public void run() {
producer = new Monitor();
System.out.println("Producer created");
try {
while(true) {
producer.produce();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer implements Runnable {
Monitor consumer;
public Consumer(Monitor m) {
consumer = m;
}
#Override
public void run() {
System.out.println("Consumer created");
consumer = new Monitor();
try {
while(true) {
consumer.consume();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class monitorTest {
public static void main(String args[]) {
Monitor monitor = new Monitor(10);
Thread t1 = new Thread(new Producer(monitor));
Thread t2 = new Thread(new Consumer(monitor));
t1.start();
t2.start();
}
}
When the control of each thread enters the produce() or consume() methods, the size and length are both zero and hence both threads are waiting for the other to notify. Break this and your code will come out of the deadlock.
public synchronized void produce() throws InterruptedException {
while(size == length) { // size is 0 and length is 0; so wait
System.out.println("Producer waiting");
wait();
}
public synchronized void consume() throws InterruptedException {
while(size == 0) { // size is 0 so wait
System.out.println("Consumer waiting, size " + size);
wait();
}
This is happening because you have a default constructor which you are calling inside the run() method of your Producer and Consumer objects.
class Producer implements Runnable {
Monitor producer;
public Producer(Monitor m) {
producer = m;
}
#Override
public void run() {
producer = new Monitor(); // REMOVE THIS
class Consumer implements Runnable {
Monitor consumer;
public Consumer(Monitor m) {
consumer = m;
}
#Override
public void run() {
System.out.println("Consumer created");
consumer = new Monitor(); // AND REMOVE THIS
Hope this helps!
Below Room is the class which lets threads enter and exit from a room. Orchestrate_enque_deque is the class that will help thread enter and then do the increment of synchronized variable and wait till all the thread finish.
What I am supposed to do :
The last thread to finish will call the exit handler. The exit handler will then again notify all the thread to enter to next room and again continue this until the last room.
My question :
How can I know when is the last thread executed?
When room 0 is entered 13 threads are created. All 13 thread increment() the shared variable. Threads must wait till all the thread have finished calculation. Now how can I know that all the thread have finished calculation.
Inside the funcition work of Orchestrate_enque_deque
increase();
System.out.println(count);
while(roomobj.enter_room){
cond.await();
System.out.println("now before signal all");
}
Each thread increase and wait and is never signaled to wake up.
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Rooms{
int room;
boolean enter_room = true;
int which_room=0;
public interface Handler{
void onEmpty() throws InterruptedException;
}
public Rooms(int m){
this.room = m;
}
public void enter(int i){
System.out.println("room.enter "+ i );
if(which_room == i) {
enter_room = true;
}
}
public boolean exit(){
if(room < which_room)
return true;
else
{
return false;
}
}
public void setExitHandler(int i, Rooms.Handler h) throws InterruptedException {
h.onEmpty();
}
}
class Orchestrate_enque_deque implements Rooms.Handler{
int count = 0;
final Lock lock = new ReentrantLock();
final Condition cond = lock.newCondition();
Rooms roomobj;
int which_room = 0;
int room_no;
Rooms.Handler handler;
Orchestrate_enque_deque(int room_no){
this.room_no = room_no;
roomobj = new Rooms(room_no);
}
public boolean when_to_exit(){
return roomobj.exit();
}
public void increase(){
for(int i =0;i <100;i++){
count++;
}
}
public void work() throws InterruptedException{
lock.lock();
//while()
// wait till all thread finish job in room.
while(roomobj.enter_room == false)
cond.await();
roomobj.enter(which_room);
try{
if(which_room >0 && which_room < room_no){
System.out.println("orchestrate work : which_room" + which_room );
cond.signalAll();
}
increase();
System.out.println(count);
while(roomobj.enter_room){
cond.await();
System.out.println("now before signal all");
}
//roomobj.setExitHandler(i, h);
}finally{
// roomobj.setExitHandler(i, handler);
lock.unlock();
}
}
public void onEmpty() throws InterruptedException {
roomobj.enter_room = false;
which_room++;
System.out.println("inside onEmpty : which_room after adding" + which_room);
}
}
class Worker extends Thread{
Orchestrate_enque_deque obj;
public Worker(Orchestrate_enque_deque obj){
this.obj = obj;
}
public void run(){
try {
while(!obj.when_to_exit()){
obj.work();
//System.out.println(" I am thread doing run with id "+Thread.currentThread().getId() );
obj.onEmpty();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Simulate{
public static void main(String args[]) throws InterruptedException {
int NO_OF_THREADS = 13;
Orchestrate_enque_deque Orchestrate_obj = new Orchestrate_enque_deque(4);
Worker[] worker_obj = new Worker[NO_OF_THREADS];
for(int i = 0; i < NO_OF_THREADS;i++){
worker_obj[i] = new Worker(Orchestrate_obj);
worker_obj[i].start();
}
for(int j = 0; j < NO_OF_THREADS;j++){
worker_obj[j].join();
}
}
}
I would look into the CompletionService Api provided by in java.util.concurrent
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CompletionService.html
Odd even number printing using thread.Create one thread class, two instance of the thread. One will print the odd number and the other will print the even number.
I did the following coding. But it comes to dead lock state. Can some one please explain what might be the reason for that?
public class NumberPrinter implements Runnable{
private String type;
private static boolean oddTurn=true;
public NumberPrinter(String type){
this.type=type;
}
public void run() {
int i=type.equals("odd")?1:2;
while(i<10){
if(type.equals("odd"))
printOdd(i);
if(type.equals("even"))
printEven(i);
i=i+2;
}
}
private synchronized void printOdd(int i){
while(!oddTurn){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(type + i);
oddTurn=false;
notifyAll();
}
private synchronized void printEven(int i){
while(oddTurn){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(type + i);
oddTurn=true;
notifyAll();
}
public static void main(String[] s){
Thread odd=new Thread(new NumberPrinter("odd"));
Thread even=new Thread(new NumberPrinter("even"));
odd.start();
even.start();
}
}
Out Put:
odd1
even2
then comes to deadlock!!!!!!
Thanks for your help.
You're waiting and notifying different objects (monitors).
The idea is that you can call obj.wait() to wait for someone to do obj.notify(), while you're doing objA.wait() and objB.notify().
Change your printOdd method to something like
private void printOdd(int i) {
synchronized (lock) { // <-------
while (!oddTurn) {
try {
lock.wait(); // <-------
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(type + i);
oddTurn = false;
lock.notifyAll(); // <-------
}
}
and the printEven method similarly.
Then provide the NumberPrinter with a lock object:
Object lock = new Object();
Thread odd = new Thread(new NumberPrinter("odd", lock));
Thread even = new Thread(new NumberPrinter("even", lock));
Output:
odd1
even2
odd3
even4
odd5
even6
odd7
even8
odd9
There are a lot of bugs in the code.
First of all, the synchronized statements have no effect whatsoever. You create two thread instances, and each calls only its own methods. synchronized is only useful if another thread can call a method.
Then notifyAll() has no effect for the same reasons. odd.notifyAll() doesn't reach even hanging in the wait().
So what you need is another object which contains the state and which both threads can see and use. Use synchronized, wait() and notifyAll() on that third instance.
The same can be solved using Lock interface:
NaturalOrder.java
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class NaturalOrder {
public int currentNumber = 1;
public boolean evenOdd = false;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
public static void main(String[] args) {
NaturalOrder naturalOrder = new NaturalOrder();
Thread t1 = new Thread(new OddNumberLock(naturalOrder, naturalOrder.lock, naturalOrder.condition));
Thread t2 = new Thread(new EvenNumberLock(naturalOrder, naturalOrder.lock, naturalOrder.condition));
t1.start();
t2.start();
}
}
OddNumberLock.java
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class OddNumberLock implements Runnable {
NaturalOrder naturalOrder;
Lock lock;
Condition condition;
public OddNumberLock(NaturalOrder naturalOrder, Lock lock, Condition condition) {
this.naturalOrder = naturalOrder;
this.lock = lock;
this.condition = condition;
}
#Override
public void run() {
lock.lock();
while (naturalOrder.currentNumber < 20) {
while (naturalOrder.evenOdd != false) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(ThreadLocalRandom.current().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
if (naturalOrder.currentNumber % 2 != 0) {
System.out.println(naturalOrder.currentNumber);
}
naturalOrder.currentNumber++;
naturalOrder.evenOdd = true;
condition.signalAll();
}
lock.unlock();
}
}
EvenNumberLock.java
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class EvenNumberLock implements Runnable {
NaturalOrder naturalOrder;
Lock lock;
Condition condition;
public EvenNumberLock(NaturalOrder naturalOrder, Lock lock, Condition condition) {
this.naturalOrder = naturalOrder;
this.lock = lock;
this.condition = condition;
}
#Override
public void run() {
lock.lock();
while (naturalOrder.currentNumber < 20) {
while (naturalOrder.evenOdd != true) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(ThreadLocalRandom.current().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
if (naturalOrder.currentNumber % 2 == 0) {
System.out.println(naturalOrder.currentNumber);
}
naturalOrder.currentNumber++;
naturalOrder.evenOdd = false;
condition.signalAll();
}
lock.unlock();
}
}
I think the problem might be that printOdd and printEven synchronize on different lock (the Thread's object instance locks). Therefor you have not guaranteed that the change on the static variable oddTurn will be visible in the other thread. Try to make the oddTurn volatile for the start.
I did this way
public class OddEven{
public static void main(String[] args){
Print o=new Print();
Thread even=new Thread(new MyRunnable(2,o));
Thread odd=new Thread(new MyRunnable(1,o));
even.start();
odd.start();
}
}
class MyRunnable implements Runnable{
int start;
Print ob;
MyRunnable(int s,Print o){
start=s;
ob=o;
}
public void run(){
for(int i=start;i<=20;i+=2)
ob.display(i);
}
}
class Print{
int rem=0;
synchronized void display(int n){
while(n%2==rem)
try{
wait();
}
catch(Exception e){System.out.println("Display interrupted");}
System.out.print(n+" ");
rem=n%2;
notify();
}
}
You're missing volatile keyword within oddTurn variable. Without it there are no guarantees the threads see the actual value.
i Used a shared object to control the order of execution
class Counter implements Runnable {
int count;
static Class cl = Counter.class;
public synchronized void increment() {
String tname = Thread.currentThread().getName();
System.out.printf("%s: %d\n", tname, count++);
}
#Override
public void run() {
String tname = Thread.currentThread().getName();
while (true) {
increment();
synchronized (Counter.class) {
try {
cl.notify();
cl.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public class WaitNotify {
public static void main(String[] args) {
Counter c = new Counter();
Thread t1 = new Thread(c, "thread1");
Thread t2 = new Thread(c, "thread2");
t1.start();
t2.start();
}
}
Here's my solution without any waits or notify.
wait() and notify()/notifyAll() ,
I dont see any reason to use them for this problem statement.
package threading;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class EvenOddPrinting {
int count=0;
boolean isOdd = false;
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
EvenOddPrinting obj = new EvenOddPrinting();
exec.submit(new EvenPrinter(obj));
exec.submit(new OddPrinter(obj));
exec.shutdown();
}
}
class EvenPrinter implements Runnable{
EvenOddPrinting obj;
public EvenPrinter(EvenOddPrinting obj) {
this.obj=obj;
}
#Override
public void run() {
while(obj.count < 100){
if(!obj.isOdd){
System.out.println("Even:"+obj.count);
obj.count++;
obj.isOdd = true;
}
}
}
}
class OddPrinter implements Runnable{
EvenOddPrinting obj;
public OddPrinter(EvenOddPrinting obj) {
this.obj = obj;
}
#Override
public void run() {
while(obj.count < 100){
if(obj.isOdd){
System.out.println("Odd:"+obj.count);
obj.count++;
obj.isOdd = false;
}
}
}
}
Your code corrected with using Lock interface:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class NumberPrinter implements Runnable {
private Lock lock;
private Condition condition;
private String type;
private static boolean oddTurn = true;
public NumberPrinter(String type, Lock lock, Condition condition) {
this.type = type;
this.lock = lock;
this.condition = condition;
}
public void run() {
int i = type.equals("odd") ? 1 : 2;
while (i <= 10) {
if (type.equals("odd"))
printOdd(i);
if (type.equals("even"))
printEven(i);
i = i + 2;
}
}
private void printOdd(int i) {
// synchronized (lock) {
lock.lock();
while (!oddTurn) {
try {
// lock.wait();
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(type + " " + i);
oddTurn = false;
// lock.notifyAll();
condition.signalAll();
lock.unlock();
}
// }
private void printEven(int i) {
// synchronized (lock) {
lock.lock();
while (oddTurn) {
try {
// lock.wait();
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(type + " " + i);
oddTurn = true;
// lock.notifyAll();
condition.signalAll();
lock.unlock();
}
// }
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
Thread odd = new Thread(new NumberPrinter("odd", lock, condition));
Thread even = new Thread(new NumberPrinter("even", lock, condition));
odd.start();
even.start();
}
}
public class Number_Thread extends Thread {
String thread;
int limit;
public Number_Thread(String thread,int limit){
this.thread=thread;
this.limit=limit;
}
Object lock=new Object();
public void run()
{
synchronized (lock)
{
//------------------- "print even"--------------------//
if(thread.equals("even"))
{
for (int i = 2; i <=limit; i+=2)
{
System.out.println(thread+" thread "+i);
try {
lock.wait(1000);
continue;
}
catch (InterruptedException e) {}
}
lock.notifyAll();
}
//------------------- "print odd"--------------------//
if(thread.equals("odd"))
{
for (int i = 1; i <=limit; i+=2)
{
System.out.println(thread+" thread "+i);
try {
lock.wait(1000);
continue;
}
catch (InterruptedException e) {}
}
lock.notifyAll();
}
}
}
}
//------------------thread creater class------------------//
import java.util.Scanner;
public class Main_Thread {
private static Scanner s;
public static void main(String[] args) throws InterruptedException {
System.out.print("enter limit:\t ");
s=new Scanner(System.in);
int n=s.nextInt();
s.close();
Thread t1=new Number_Thread("even",n);
Thread t2=new Number_Thread("odd",n);
t2.start();
Thread.sleep(100);
t1.start();
}
}
output for limit 5:
enter limit: 5
odd thread 1
even thread 2
odd thread 3
even thread 4
odd thread 5
I have implemented in such a way, based on the argument, no of threads will be spawned and will the respective no in round robin manner.
i.e., If thread count is 3, thread 1 will print 1,4 ...; thread 2 will print 2,5,... and thread 3 will print 3,6...
public class ThreadSynchronizer
{
public static void main(String[] args)
{
// BASED ON THE ARGUMENT MULTIPLE THREADS WILL BE CREATED AND EACH WILL PRINT ITS RESPECTIVE NO
// IE, IF THREAD COUNT IS 3, THREAD 1 WILL PRINT 1,4 ..., THREAD2 WILL PRINT 2,5,... AND THREAD3 WILL PRINT 3,6...
// LIMITED THE DISPLAY TO 1000 NOS
int threadCnt = Integer.parseInt(args[0]);
ReentrantLock lckArray[] = new ReentrantLock[threadCnt + 1];
for (int i = 0; i < threadCnt + 1; i++)
{
ReentrantLock lck = new ReentrantLock();
lck.lock();
lckArray[i] = lck;
}
for (int i = 0; i < threadCnt; i++)
{
Thread th = new Thread(new Printer(lckArray, i + 1));
th.start();
}
for (int i = 1; i < threadCnt + 1; i++)
{
lckArray[i].unlock();
while (!lckArray[i].isLocked())
{
}
}
lckArray[0].unlock();
}
}
class Printer implements Runnable
{
private ReentrantLock[] lckArray;
private int index;
Printer(ReentrantLock[] lckArray, int startValue)
{
this.lckArray = lckArray;
this.index = startValue;
}
#Override public void run()
{
ReentrantLock prevLock = null;
int printCounter = index;
for (int counter = 0; printCounter <= 1000; counter++)
{
int remCounter = counter % lckArray.length;
int incCounter = lckArray.length - remCounter;
int indexPostion = index + incCounter;
int curElementIndex = indexPostion % lckArray.length;
lckArray[curElementIndex].lock();
if (prevLock != null)
prevLock.unlock();
prevLock = lckArray[curElementIndex];
if (curElementIndex == 0)
{
System.out.println("Printed by Thread " + index + " " + printCounter);
printCounter = printCounter + lckArray.length - 1;
}
}
if (prevLock != null)
{
if (prevLock.isHeldByCurrentThread())
prevLock.unlock();
}
}
}
Program for Two Threads Alternatively Print Odd and Even Numbers.
#Implemented Using "Object Lock" Concept.
class Increment{
private int count;
public void increment(){
count++;
System.out.println(Thread.currentThread().getName()+"::::::::::::::::::"+count);
}
}
class SimpleThread extends Thread{
Increment obj = null;
SimpleThread(Increment obj){
this.obj=obj;
}
public void run(){
try {
Thread.sleep(100);
while(true){
synchronized(obj){
obj.increment();
Thread.sleep(1000);
obj.notify();
obj.wait();
}
}
} catch(InterruptedException ie) {
ie.printStackTrace();
}
}
}
public class Main
{
public static void main(String[] args) {
Increment increment = new Increment();
SimpleThread t1 = new SimpleThread(increment);
SimpleThread t2 = new SimpleThread(increment);
t1.start();
t2.start();
System.out.println(Thread.currentThread().getName()+"::::::::::::::"+"Hello World");
System.out.println(Runtime.getRuntime().availableProcessors()+"::::::::::::::"+"CORE SIZE");
}
}
I implemented it in a very simple way, from 1 to 40>
public class EvenOddProblem {
public static void main(String[] args) {
Printer p = new Printer();
EvenThread enenThread = new EvenThread(p);
OddThread oddThread = new OddThread(p);
new Thread(enenThread).start();
new Thread(oddThread).start();
}
}
class EvenThread implements Runnable {
private Printer printer;
public EvenThread(Printer p) {
printer = p;
}
#Override
public void run() {
try {
int i = 0;
while (true) {
if (i == 20)
break;
i++;
printer.evenPrintEven();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class OddThread implements Runnable {
private Printer printer;
public OddThread(Printer p) {
printer = p;
}
#Override
public void run() {
int i = 0;
try {
while (true) {
if (i == 20)
break;
i++;
printer.evenPrintOdd();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Printer {
private static volatile Integer i = 1;
public synchronized void evenPrintOdd() throws InterruptedException {
while (i % 2 == 0) {
wait();
}
System.out.println(i);
i++;
notifyAll();
}
public synchronized void evenPrintEven() throws InterruptedException {
while (!(i % 2 == 0)) {
wait();
}
System.out.println(i);
i++;
notifyAll();
}
}