Objective : To create two threads such that producer and consumer threads work interchangeably i.e if first thread acts as producer than second act as consumer and vice versa.
Details : They communicate with each other through a buffer,Storing one integer size. For example if first thread produces 1 then second thread consumes it and produces 2 and then the first thread consumes 2 and produces next three integers and Consumer consumes them one by one.
Both threads terminate after that.
Also both threads should be able to initiate the communication.
I tried to write the following code.
import java.util.Random;
class CommonItem {
boolean flag = false;
int arr[];
public synchronized void Send(String msg) {
if (flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(msg);
flag = true;
notify();
}
public synchronized void Receive(String msg) {
if (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(msg);
arr = send_random();
for (int item: arr) {
System.out.println(item);
}
flag = false;
notify();
}
synchronized int[] send_random(){
int[] arr = new int[3];
Random random= new Random();
for (int i = 0; i < 3; i++) {
arr[i]=random.nextInt(100);
}
return arr;
}
}
class T1 implements Runnable {
CommonItem Ci;
public T1(CommonItem Ci) {
this.Ci = Ci;
new Thread(this, "producer").start();
}
public void run() {
while (true)
Ci.Send("sent :1");
}
}
class T2 implements Runnable {
CommonItem Ci;
public T2(CommonItem m2) {
this.Ci = m2;
new Thread(this, "Consumer").start();
}
public void run() {
while (true)
Ci.Receive("received :2");
}
}
public class TestClass {
public static void main(String[] args) {
CommonItem m = new CommonItem();
new T1(m);
new T2(m);
}
}
The expected output is
sent :1
received :1
sent :2
received :2
sent :57 4 13
received :57 4 13
But I get the following output
OUTPUT
sent :1
received :2
57
4
13
Please suggest if any correction in the code or any idea on how to solve the given problem in an alternate way. Thank you in advance.
public class CommonItem {
boolean receiver = false;
List<Integer> list = new ArrayList<>();
public void receive() throws InterruptedException {
String name = Thread.currentThread().getName();
synchronized (list) {
while (list.isEmpty()) {
list.notify();
list.wait();
}
// Receive all elements
System.out.printf("Receiving elements by %s:\t", name);
for (int val : list) {
System.out.print(val + " ");
}
list.clear();
System.out.println();
list.notify();
list.wait();
}
}
public void send() throws InterruptedException {
String name = Thread.currentThread().getName();
synchronized (list) {
while (!list.isEmpty()) {
list.notify();
list.wait();
}
// Sending elements
int[] arr = get_random();
System.out.printf("Sending elements by %s\t", name);
for (int ele : arr) {
list.add(ele);
System.out.print(ele + " ");
}
System.out.println();
list.notify();
list.wait();
}
}
public int[] get_random() throws InterruptedException {
int[] arr = new int[3];
Random random = new Random();
for (int i = 0; i < 3; i++) {
arr[i] = random.nextInt(100);
}
Thread.sleep(1000);
return arr;
}
}
public class ThreadTask implements Runnable {
private CommonItem item;
private boolean receiver;
public ThreadTask(CommonItem item, boolean receiver) {
this.item = item;
this.receiver = receiver;
}
public static void main(String[] args) {
CommonItem item = new CommonItem();
Thread t1 = new Thread(new ThreadTask(item, false), "First");
Thread t2 = new Thread(new ThreadTask(item, true), "Second");
t1.start();
t2.start();
}
#Override
public void run() {
while (true) {
try {
if (receiver) {
item.receive();
} else {
item.send();
}
receiver = !receiver;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Sending elements by First 25 6 57
Receiving elements by Second: 25 6 57
Sending elements by Second 35 99 10
Receiving elements by First: 35 99 10
Sending elements by First 84 11 1
Receiving elements by Second: 84 11 1
Sending elements by Second 68 91 53
Receiving elements by First: 68 91 53
package java11;
import java.util.*;
import java.util.Random;
class CommonItem
{
boolean receiver = false;
List<Integer> list = new ArrayList<>();
int k=1;
public void receive() throws InterruptedException
{
String name = Thread.currentThread().getName();
synchronized (list)
{
while (list.isEmpty())
{
list.notify();
list.wait();
}
// Receive all elements
System.out.printf("Receiving elements by %s:\t", name);
for (int val : list)
{
System.out.print(val + " ");
}
list.clear();
System.out.println();
list.notify();
list.wait();
}
}
public void send(int i) throws InterruptedException
{
String name = Thread.currentThread().getName();
synchronized (list)
{
while (!list.isEmpty())
{
list.notify();
list.wait();
}
// Sending elements
int[] arr;
if(i<3)
{
arr = get_random(k);
k++;
}
else
{
arr = get_random1();
}
System.out.printf("Sending elements by %s\t", name);
for (int ele : arr)
{
list.add(ele);
System.out.print(ele + " ");
}
System.out.println();
list.notify();
list.wait();
}
}
public int[] get_random(int k) throws InterruptedException
{
int[] arr = new int[1];
arr[0] = k;
Thread.sleep(1000);
return arr;
}
public int[] get_random1() throws InterruptedException
{
int[] arr = new int[3];
Random random = new Random();
for (int i = 0; i < 3; i++)
{
arr[i] = random.nextInt(100);
}
Thread.sleep(1000);
return arr;
}
}
public class Java11 implements Runnable
{
private CommonItem item;
private boolean receiver;
public Java11(CommonItem item, boolean receiver)
{
this.item = item;
this.receiver = receiver;
}
public static void main(String[] args)
{
int choice;
CommonItem item = new CommonItem();
System.out.println("Who should start first?:Thread 1 or Thread 2");
Scanner sc=new Scanner(System.in);
choice=sc.nextInt();
if(choice==1)
{
Thread t1 = new Thread(new Java11(item, false), "First");
Thread t2 = new Thread(new Java11(item, true), "Second");
t1.start();
t2.start();
}
else if(choice==2)
{
Thread t1 = new Thread(new Java11(item, true), "First");
Thread t2 = new Thread(new Java11(item, false), "Second");
t1.start();
t2.start();
}
}
#Override
public void run()
{
int i=1;
while (i<=3)
{
try
{
if (receiver)
{
item.receive();
}
else
{
item.send(i);
}
receiver = !receiver;
}
catch(InterruptedException e)
{
e.printStackTrace();
}
i++;
}
}
}
Slight changes are made in Sanit's code to get exact output as demanded by the problem statement.
OUTPUT:
Who should start first?:Thread 1 or Thread 2
1
Sending elements by First 1
Receiving elements by Second: 1
Sending elements by Second 2
Receiving elements by First: 2
Sending elements by First 90 95 28
Receiving elements by Second: 90 95 28
Who should start first?:Thread 1 or Thread 2
2
Sending elements by Second 1
Receiving elements by First: 1
Sending elements by First 2
Receiving elements by Second: 2
Sending elements by Second 42 10 33
Receiving elements by First: 42 10 33
Thank you #Sanit.
Solved- #Kunjan Rana
I want to use data structure which can be constantly accesed by multithreaded code . Please let me know any Data structure in java , where I can wait and use notify options . Kindly see the below code , why run method of CDRemove doesnot print all values
public class ConcurrencyDemo {
public static void main(String[] args) throws InterruptedException {
CopyOnWriteArrayList<String> threadSafeList = new CopyOnWriteArrayList<String>();
CDInsert cd1 = new CDInsert(threadSafeList);
CDRemove cr1 = new CDRemove(threadSafeList);
cd1.start();
cr1.start();
}
}
class CDInsert extends Thread
{
List threadSafeList;
public CDInsert(List threadSafeList) {
this.threadSafeList = threadSafeList;
}
public void run()
{
int counter = 0;
while(counter < 20){
counter++;
threadSafeList.add(String.valueOf(counter));
System.out.println("Counter value is "+counter);
}
}
public void showItem(){
Iterator<String> failSafeIterator = threadSafeList.iterator();
while(failSafeIterator.hasNext()){
System.out.printf("Read from CopyOnWriteArrayList : %s %n", failSafeIterator.next());
}
}
}
class CDRemove extends Thread {
List threadSafeList;
public CDRemove(List threadSafeList) {
this.threadSafeList = threadSafeList;
}
public void run(){
Iterator<String> failSafeIterator = threadSafeList.iterator();
System.out.println("Fail Safe Iterator is "+failSafeIterator);
while(true){
System.out.println("Fail Safe Iterator is "+failSafeIterator);
while(failSafeIterator.hasNext()){
System.out.printf("Read from CopyOnWriteArrayList : %s %n", failSafeIterator.next());
}
}
}
}
thread CDRemove has an infinite loop:
while(true){ // Change this.
while(failSafeIterator.hasNext()){
System.out.printf("Read from CopyOnWriteArrayList : %s %n", failSafeIterator.next());
}
}
Now the iterator will represent the state of the list when constructed. If the CDInsert thread was still running, the iterator would not have all the elements.
I am creating a system that will have multiple suite deployments and each deployment will have a queue of test suites. Since I want the test suites to run concurrently on their individual suite deployment, I need to add concurrency to the code. I have created a simplified version of the code I am using, but the concurrency portion doesn't work when I try to shut it down.
When the Runner.stopEverything() gets called, the result is that the queue gets emptied, and it waits for the threads to complete, but even when the tests all complete, the wait never finishes even with the notifyAll(). The result is that the process just sits there never ending. I go look at it in debug mode and the result is that all 3 threads show waiting.
Main:
public static void main(String args[]) throws Exception {
Runner.queueTestSuites("SD1", Arrays.asList("A", "B", "C"));
Runner.queueTestSuites("SD2", Arrays.asList("D", "E", "F"));
Runner.queueTestSuites("SD3", Arrays.asList("G", "H", "I"));
Thread.sleep(5000);
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~");
Runner.stopEverything();
}
Runner:
public class Runner {
private static Map<String, TestQueue> runnerQueueMap = new ConcurrentHashMap<>();
public synchronized static void queueTestSuites(String suiteDeployment, List<String> testSuiteQueueAsJSON) throws Exception {
TestQueue queue;
if(runnerQueueMap.containsKey(suiteDeployment)) {
queue = runnerQueueMap.get(suiteDeployment);
} else {
queue = new TestQueue(suiteDeployment);
}
for (int i = 0; i < testSuiteQueueAsJSON.size(); i++) {
String name = testSuiteQueueAsJSON.get(i);
queue.addToQueue(name);
}
runnerQueueMap.put(suiteDeployment,queue);
}
public synchronized static void stopEverything() throws InterruptedException {
for (String s : runnerQueueMap.keySet()) {
TestQueue q = runnerQueueMap.get(s);
q.saveAndClearQueue();
}
for (String s : runnerQueueMap.keySet()) {
TestQueue q = runnerQueueMap.get(s);
q.waitForThread();
}
System.out.println("All done at " + new Date());
}
}
TestQueue:
public class TestQueue {
private Consumer consumer;
private Thread consumerThread;
private java.util.concurrent.BlockingQueue<String> queue;
private String suiteDeployment;
public TestQueue(String suiteDeployment) {
this.suiteDeployment = suiteDeployment;
queue = new ArrayBlockingQueue<>(100);
startConsumer();
}
public void addToQueue(String testSuite) {
try {
queue.put(testSuite);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void waitForThread() {
try {
if (consumer.running.get()) {
synchronized (consumerThread) {
System.out.println("Waiting for " + consumerThread.getName());
consumerThread.wait();
}
}
System.out.println("Thread complete at " + new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void saveAndClearQueue() {
List<String> suiteNames = new ArrayList<>();
for (String suite : queue) {
suiteNames.add(suite);
}
queue.clear();
}
private void startConsumer() {
consumer = new Consumer(queue,suiteDeployment);
consumerThread = new Thread(consumer);
consumerThread.start();
}
private class Consumer implements Runnable{
private BlockingQueue<String> queue;
private String suiteDeployment;
public AtomicBoolean running;
public Consumer(BlockingQueue<String> queue, String suiteDeployment){
this.queue = queue;
this.suiteDeployment = suiteDeployment;
this.running = new AtomicBoolean(false);
}
#Override
public void run() {
try{
while(!Thread.currentThread().isInterrupted()) {
String testSuite = queue.take();
this.running.set(true);
new Test(testSuite, suiteDeployment).run();
this.running.set(false);
}
notifyAll();
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
Test:
public class Test {
String testSuite = "";
String suiteDeployment = "";
public Test(String testSuite, String suiteDeployment) {
this.testSuite = testSuite;
this.suiteDeployment = suiteDeployment;
}
public void run() {
int time = new Random().nextInt() % 10000;
time = Math.max(time, 3000);
System.out.println("Test Started: " + testSuite + " on " + suiteDeployment + " at " + new Date() + " running for " + time + " on thread " + Thread.currentThread().getName());
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Test Completed: " + testSuite + " on " + suiteDeployment + " at " + new Date());
}
}
Inside run method of your consumer, you have a blocking call to queue.take() which means it will block until there is an item inside your queue. You run out of elements inside the queue eventually and all your thread are blocked by the queue.take() call waiting for more elements to become available to process.
Although your call is in a while loop where it check if the thread is interrupted, you actually never interrupt the threads so it never gets to the while loop evaluation & blocked at the call to queue.take()
So your threads stay in wait as they are waiting for input to become avilable inside your blocking queue
Also your saveAndClear method must lock on the correct object which is the queue itself, like below:
public void saveAndClearQueue() {
List<String> suiteNames = new ArrayList<String>();
synchronized (queue) {
for (String suite : queue) {
suiteNames.add(suite);
}
queue.clear();
}
System.out.println("Saved(not executed) : "+suiteNames);
}
And your waitForThread method should do sth like below:
public void waitForThread() {
synchronized (consumerThread) {
while (consumer.running.get()) {
try {
consumerThread.wait(100);
} catch (InterruptedException e) {
break;
}
}
}
if (!consumer.running.get()) {
consumerThread.interrupt();
}
System.out.println("Thread complete at " + new Date());
}
I am trying to create an implementation where multiple threads print alternate values of sequence. So here thread1 will print 1,4,7 thread2 will print 2,5,8 thread3 will print 3,6,9. I am using Atomic integer and modulo function.
Below implementation works fine in the sense that first thread prints 1,4,7 while second prints 2,5,8 and third prints 3,6,9 but problem is that sequence is not maintained i.e output can be like 1,3,2,4,5,7,8,6,9 while i want sequence to be maintained as proper threads shld print those values.
One condition is i don't want to use synchronize. [Just for learning purpose]
import java.util.concurrent.atomic.AtomicInteger;
public class ThreeThreadsOrderedLockLess {
AtomicInteger sharedOutput = new AtomicInteger(0);
public static void main(String args[]) {
ThreeThreadsOrderedLockLess t = new ThreeThreadsOrderedLockLess();
ThreadTasks t1 = t.new ThreadTasks(0);
ThreadTasks t2 = t.new ThreadTasks(1);
ThreadTasks t3 = t.new ThreadTasks(2);
Thread ts1 = new Thread(t1);
Thread ts2 = new Thread(t2);
Thread ts3 = new Thread(t3);
ts1.start();
ts2.start();
ts3.start();
}
private class ThreadTasks implements Runnable {
private final int threadPosition;
public ThreadTasks(int threadPosition) {
super();
this.threadPosition = threadPosition;
}
#Override
public void run() {
while (sharedOutput.get() < 9) {
if (sharedOutput.get() % 3 == this.threadPosition) {
System.out.println("Printing output for Thread: "
+ this.threadPosition + " "
+ sharedOutput.incrementAndGet());
}
}
}
}
}
You should print first, and increment after:
int value = sharedOutput.get() + 1;
System.out.println("Printing output for Thread: "
+ this.threadPosition + " "
+ value);
sharedOutput.incrementAndGet();
That said, all the threads are busy looping, which will lead to 100% CPU usage. You should synchronize the threads instead.
Below code snippet will print numbers in sequence and all threads will be terminated gracefully after the task.
Used AtomicInteger, which is thread-safe for printing the numbers and same logic can be applied to print as till any number with any number of threads.
import java.util.concurrent.atomic.AtomicInteger;
public class PrintNumSequence
{
public static void main(String[] args)
{
AtomicInteger atomicInteger = new AtomicInteger(0);
new NumPrinter(atomicInteger, 0).start();// thread0
new NumPrinter(atomicInteger, 1).start();// thread1
new NumPrinter(atomicInteger, 2).start();// thread2
}
}
class NumPrinter extends Thread
{
private AtomicInteger atomicInteger;
private int threadNum;
public NumPrinter(AtomicInteger atomicInteger, int threadNum)
{
this.atomicInteger = atomicInteger;
this.threadNum = threadNum;
}
#Override
public void run()
{
int num = atomicInteger.intValue();
do
{
synchronized (atomicInteger)
{
num = atomicInteger.intValue();
// If number is 9 then stop.
if (num > 9)
{
atomicInteger.notifyAll();
break;
}
// 3 is number of threads
if ((num % 3) == threadNum)
{
System.out.println("Thread-" + threadNum + " -->" + num);
num = atomicInteger.incrementAndGet();
}
atomicInteger.notifyAll();
try
{
atomicInteger.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
} while (true);
}
}
This is because the time slice for each thread is determined by the OS. So it is possible that thread x increments the shared number but before printing the time slice is passed to the next thread y which now reads the shared number and prints it after incrementing (assuming that thread y got more time than thread x to increament and print the shared number)
.
use wait(), notify(), notifyall() methods of the Java.
you can also take a look at this Tutorial of these methods.
Hope this would be helpful to solve your issue. . .
the output of this example is as under.
Put: 1
Got: 1
Put: 2
Got: 2
Put: 3
Got: 3
Put: 4
Got: 4
Put: 5
Got: 5
This should work:
package com.sid;
import java.util.concurrent.atomic.AtomicInteger;
public class NumberSequence {
private AtomicInteger sharedOutput = new AtomicInteger(0);
private Object object = new Object();
public static void main(String args[]) {
NumberSequence t = new NumberSequence();
ThreadTasks t1 = t.new ThreadTasks(0);
ThreadTasks t2 = t.new ThreadTasks(1);
ThreadTasks t3 = t.new ThreadTasks(2);
Thread ts1 = new Thread(t1);
Thread ts2 = new Thread(t2);
Thread ts3 = new Thread(t3);
ts1.start();
ts2.start();
ts3.start();
}
private class ThreadTasks implements Runnable {
private final int threadPosition;
public ThreadTasks(int threadPosition) {
super();
this.threadPosition = threadPosition;
}
#Override
public void run() {
while (sharedOutput.get() < 10) {
synchronized (object) {
if (sharedOutput.get() % 3 == this.threadPosition) {
if(sharedOutput.get() < 10)
System.out.println("Printing output for Thread: "
+ this.threadPosition + " "
+ sharedOutput.incrementAndGet());
}
}
}
}
}
}
Proper synchronization would help you get the clear answer. I've improved the implementation, you should solve your questions.
int threadId;
int moduluos;
int numOfThreads;
public ThreadTasks(int id, int nubOfThreads) {
threadId = id;
this.numOfThreads = nubOfThreads;
moduluos = threadId%numOfThreads;
}
public void run() {
print();
}
private void print() {
try {
while (true) {
synchronized (monitor) {
if (number.get() % numOfThreads != moduluos) {
monitor.wait();
} else {
System.out.println("ThreadId [" + threadId
+ "] printing -->"
+ number.getAndIncrement());
monitor.notifyAll();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package test.mk.thread;
import java.util.concurrent.atomic.AtomicInteger;
public class MkThread2 {
int nextThreadToRun = 1;
int[] arr = {1,2,3,4,5,6,7,8,9,10,11};
AtomicInteger nextArrayIndex = new AtomicInteger(0);
boolean token = true;
public static void main(String[] args) {
MkThread2 mkThread = new MkThread2();
Thread t1 = new Thread(new Worker2(1, mkThread));
Thread t2 = new Thread(new Worker2(2, mkThread));
Thread t3 = new Thread(new Worker2(3, mkThread));
t1.start();
t2.start();
t3.start();
}
}
class Worker2 implements Runnable{
volatile int threadNo;
private MkThread2 mkThread;
private String threadName;
Worker2(int threadNo, MkThread2 mkThread){
this.threadNo = threadNo;
this.mkThread = mkThread;
this.threadName = "Thread:"+threadNo ;
}
public void run(){
try{
synchronized (mkThread) {
while(mkThread.token){
while(threadNo != mkThread.nextThreadToRun){
mkThread.wait();
}
if(mkThread.token){//double checking
System.out.print(threadName+ "->" + mkThread.arr[mkThread.nextArrayIndex.get()]);
if(threadNo == 3) System.out.println();
mkThread.nextThreadToRun = getNextThread(threadNo);
if(mkThread.nextArrayIndex.get() == mkThread.arr.length-1){
mkThread.token = false;
}
mkThread.nextArrayIndex.incrementAndGet();
}
mkThread.notifyAll();
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
private int getNextThread(int threadNo){
int result = -1;
switch (threadNo) {
case (1):
result = 2;
break;
case (2):
result = 3;
break;
case (3):
result = 1;
break;
}
return result;
}
}
import java.util.concurrent.atomic.AtomicInteger;
public class Print123456789 {
public static void main(String[] args) {
print p1 = new print(0);
print p2 = new print(1);
print p3 = new print(2);
Thread t1 = new Thread(p1);
Thread t2 = new Thread(p2);
Thread t3 = new Thread(p3);
t1.start();
t2.start();t3.start();
}
}
class print implements Runnable {
private int threadNumber;
private static AtomicInteger atomicInteger = new AtomicInteger(0);
public print(int threadNumber) {
super();
this.threadNumber = threadNumber;
}
public void run(){
try{
while(atomicInteger.get() < 10){
synchronized (atomicInteger) {
if((atomicInteger.get()%3) == this.threadNumber){
System.out.println(atomicInteger.getAndIncrement() + " Thread :" + this.threadNumber );
atomicInteger.notifyAll();
}
else
atomicInteger.wait();
}
}
}catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
This can be better implemented using blocking queues. Define a worker holding a blocking queue. The workers waits on the queue until it receives a number in it. It prints the number it receives, increments it and passes it on to the next worker in the chain. Refer here for the full solution.
package threeThread;
class Task implements Runnable {
String message;
ThreeThread lock;
int i = 0;
int p;
public Task(String text, ThreeThread obj, int p) {
message = text;
this.lock = obj;
this.p = p;
}
#Override
public void run() {
while(true) {
synchronized (lock) {
while(!((lock.status % 3) == 0) && p == 1){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while(!((lock.status % 3) == 1) && p == 2){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while(!((lock.status % 3) == 2) && p == 3){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("thread: " + p + " : " + message);
lock.status++;
lock.notifyAll();
}
}
}
}
public class ThreeThread {
volatile int status = 0;
public static void main(String[] args) {
ThreeThread lock = new ThreeThread();
Thread t1 = new Thread(new Task("Hello", lock,1));
Thread t2 = new Thread(new Task("Good", lock,2));
Thread t3 = new Thread(new Task("Morning", lock,3));
t1.start();
t2.start();
t3.start();
}
}
I am putting code to print 1-100 using 5 threads. One can use any number of thread to print output in round robin fashion.
Basic concept is to lock one object and notify other for executing the printing of value.
public class PrintOneToHundredUsing5Threads {
public static void main(String[] args) {
List<Object> objList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
objList.add(new Object());
}
for (int i = 0; i < 5; i++) {
Thread t = new Thread(new PrintThread(objList.get(i), objList.get((i + 1) % 5)));
t.setName("Thread" + i);
t.start();
}
}
}
class PrintThread implements Runnable {
Object current;
Object next;
volatile static int i = 1;
PrintThread(Object cur, Object next) {
this.current = cur;
this.next = next;
}
#Override
public void run() {
for (; i <= 100;) {
synchronized (current) {
synchronized (next) {
next.notify();
System.out.println(Thread.currentThread().getName() + " Value : " + i++);
}
try {
current.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
You can use below code to print sequential numbers using multiple threads -
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ThreadCall extends Thread {
private BlockingQueue<Integer> bq = new ArrayBlockingQueue<Integer>(10);
private ThreadCall next;
public void setNext(ThreadCall t) {
this.next = t;
}
public void addElBQ(int a) {
this.bq.add(a);
}
public ThreadCall(String name) {
this.setName(name);
}
#Override
public void run() {
int x = 0;
while(true) {
try {
x = 0;
x = bq.take();
if (x!=0) {
System.out.println(Thread.currentThread().getName() + " =>" + x);
if (x >= 100) System.exit(0); // Need to stop all running threads
next.addElBQ(x+1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int THREAD_COUNT = 10;
List<ThreadCall> listThread = new ArrayList<>();
for (int i=1; i<=THREAD_COUNT; i++) {
listThread.add(new ThreadCall("Thread " + i));
}
for (int i = 0; i < listThread.size(); i++) {
if (i == listThread.size()-1) {
listThread.get(i).setNext(listThread.get(0));
}
else listThread.get(i).setNext(listThread.get(i+1));
}
listThread.get(0).addElBQ(1);
for (int i = 0; i < listThread.size(); i++) {
listThread.get(i).start();
}
}
}
Hope this will resolve your problem.
public class PrintThreadsInSerial {
public static void main(String[] args) {
Thread t = new Thread(new Job());
t.start();
}
}
class Job implements Runnable {
#Override
public void run() {
while (true) {
for (int i = 1; i <= 3; i++) {
System.out.println(i);
}
}
}
}
The ThreadSynchronization class can be used to print numbers between 'n' no. of threads in sequence.
The logic is to create a common object between each of the consecutive threads and use 'wait', 'notify' to print the numbers in sequence.
Note: Last thread will share an object with the first thread.
You can change the 'maxThreads' value to increase or decrease the number of thread in the program before running it.
import java.util.ArrayList;
import java.util.List;
public class ThreadSynchronization {
public static int i = 1;
public static final int maxThreads = 10;
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
for (int i = 0; i < maxThreads; i++) {
list.add(new Object());
}
Object currObject = list.get(maxThreads - 1);
for (int i = 0; i < maxThreads; i++) {
Object nextObject = list.get(i);
RunnableClass1 a = new RunnableClass1(currObject, nextObject, i == 0 ? true : false);
Thread th = new Thread(a);
th.setName("Thread - " + (i + 1));
th.start();
currObject = list.get(i);
}
}
}
class RunnableClass implements Runnable {
private Object currObject;
private Object nextObject;
private boolean firstThread;
public RunnableClass(Object currObject, Object nextObject, boolean first) {
this.currObject = currObject;
this.nextObject = nextObject;
this.firstThread = first;
}
#Override
public void run() {
int i = 0;
try {
if (firstThread) {
Thread.sleep(5000);
firstThread = false;
System.out.println(Thread.currentThread().getName() + " - " + ThreadSynchronization.i++);
synchronized (nextObject) {
nextObject.notify();
}
}
while (i++ < Integer.MAX_VALUE) {
synchronized (currObject) {
currObject.wait();
}
System.out.println(Thread.currentThread().getName() + " - " + ThreadSynchronization.i++);
Thread.sleep(1000);
synchronized (nextObject) {
nextObject.notify();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class PrintSeqNumUsingAltThreads {
public static void main(String[] args) {
AtomicInteger counter = new AtomicInteger(0);
int numThreads = 3;
Thread t1 = new Thread(new SeqNumPrinter(counter, 0, numThreads));
Thread t2 = new Thread(new SeqNumPrinter(counter, 1, numThreads));
Thread t3 = new Thread(new SeqNumPrinter(counter, 2, numThreads));
t1.currentThread().setName("T1");
t2.currentThread().setName("T2");
t3.currentThread().setName("T3");
t1.start();
t2.start();
t3.start();
}
}
public class SeqNumPrinter implements Runnable {
AtomicInteger atmCounter;
Integer threadPosition;
Integer numThreads;
public SeqNumPrinter(AtomicInteger counter, int position, int numThreads) {
this.atmCounter = counter;
this.threadPosition = position;
this.numThreads = numThreads;
}
#Override
public void run() {
while (atmCounter.get() < 10) {
if (atmCounter.get() % numThreads == threadPosition) {
System.out.println("Printing value : " + atmCounter.getAndIncrement() + ", by thread : " +
Thread.currentThread().getName());
}
}
}
}
Output :
Printing value : 0, by thread : Thread-0 Printing value : 1, by
thread : Thread-1 Printing value : 3, by thread : Thread-0
Printing value : 2, by thread : Thread-2 Printing value : 4, by
thread : Thread-1 Printing value : 6, by thread : Thread-0
Printing value : 5, by thread : Thread-2 Printing value : 7, by
thread : Thread-1 Printing value : 9, by thread : Thread-0
Printing value : 8, by thread : Thread-2
I have edited my question and made it very simple.
First there are two classes on a same file
HashMapClass: which creates instance of ConccurentHashMap
and
NewThread: which updates the hashMap
public class HashMapClass {
public static volatile ConcurrentHashMap serverMap = new ConcurrentHashMap();
public static void main(String args[]) {
NewThread nt = new NewThread();
nt.start();
}
}
class NewThread extends Thread {
#Override
public void run() {
HashMapClass.serverMap.put("Ishan", new Integer(3));
System.out.println("Hash map is empty or not " + HashMapClass.serverMap.isEmpty());
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
Logger.getLogger(NewThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Now here it shows that the hashMap is not empty but if i try to access it from other class New Class it shows empty
public class NewClass {
public static void main(String s[]) {
System.out.println("Hash map is empty or not " + HashMapClass.serverMap.isEmpty());
Set setMap = HashMapClass.serverMap.entrySet();
Iterator i = setMap.iterator();
for (int f = 0; i.hasNext(); ++f) {
Map.Entry me = (Map.Entry) i.next();
System.out.println("key is" + me.getKey() + "value is :" + me.getValue());
}
}
}
this class is never updated with the data.
I hope this is easy to understand now.
HashMap is not thread safe so you need to introduce some form of synchronization if you need to share a HashMap accross threads.
Alternatively, and more simply, use a ConcurrentHashMap which is thread safe.
As a side not, you would probably benefit from reading the Java tutorial on concurrency, especially the part on Memory consistency errors.
EDIT
Following your comment, see a simple example that, I think, isolates your issue - the output on my machine is:
Hash map empty in main (1st attempt)? true
Hash map empty in run? false
Hash map empty in main (2nd attempt)? false
public class Test {
public static ConcurrentMap serverMap = new ConcurrentHashMap();
public static void main(String[] args) throws InterruptedException {
NewThread nt = new NewThread();
nt.start();
System.out.println("Hash map empty in main (1st attempt)? " + serverMap.isEmpty());
Thread.sleep(200);
System.out.println("Hash map empty in main (2nd attempt)? " + serverMap.isEmpty());
}
static class NewThread extends Thread {
#Override
public void run() {
serverMap.put("Ishan", new Integer(3));
System.out.println("Hash map empty in run? " + serverMap.isEmpty());
}
}
}
2ND EDIT
You can apply the same logic from another class - just make sure you call NewThread.start and wait enough (or just call NewThread.run directly so that it is run in the same thread and you don't have to wait):
public class NewClass {
public static void main(String s[]) throws InterruptedException {
new Test.NewThread().start();
System.out.println("Hash map is empty or not (1): " + Test.serverMap.isEmpty());
Thread.sleep(100);
System.out.println("Hash map is empty or not (2): " + Test.serverMap.isEmpty());
Set setMap = Test.serverMap.entrySet();
Iterator i = setMap.iterator();
for (int f = 0; i.hasNext(); ++f) {
Map.Entry me = (Map.Entry) i.next();
System.out.println("key is" + me.getKey() + "value is :" + me.getValue());
}
}
}
HashMap needs to be handled on its synchronization part, as its lacking thread safety
ConcurrentHashMap is better at concurrency, ConcurrentHashMap will not lock the Map while one is reading , neither will it lock the entire Map when writing to it. It gonna lock the part of the Map that is being written at present.
But its important to note that ConcurrentHashMap will not throw ConcurrentModificationException, if the ConcurrentHashMap is changed during its iteration.
Edited Code:
The problem was the HashMapClass and NewClass execution, when JVM has shutdown, after HashMapClass has completed its execution, how can we run NewClass class and try to retrieve the value which is stored in the ConcurrentHashMap, which is stored on the Heap, which is all lost as soon as jvm teminates. And yes as ConcurrentHashMap is marked static the value is stored in Memory-Area of the heap
public class HashMapClass {
public static ConcurrentHashMap<String,Integer> serverMap = new ConcurrentHashMap<String,Integer>();
public static void main(String args[]) {
NewThread nt = new NewThread();
nt.start();
try {
nt.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new NewClass().go();
}
}
class NewThread extends Thread {
#Override
public void run() {
HashMapClass.serverMap.put("Ishan", 3);
System.out.println("Hash map is empty or not " + HashMapClass.serverMap.isEmpty());
}
}
class NewClass {
public void go() {
System.out.println("Hash map is empty or not " + HashMapClass.serverMap.isEmpty());
for(Map.Entry<String,Integer> m : HashMapClass.serverMap.entrySet()){
System.out.println(m.getKey()+" "+m.getValue());
}
}
}