I am trying to learn basic concept of Multi Threading.
Why my ping pong program prints only Ping0 & Pong0, Why notify() does not start the Ping Thread which is in Wait state?
public class PingPong implements Runnable {
String word;
public PingPong(String word) {
this.word = word;
}
public void run() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.println(word + i);
try {
wait();
notifyAll();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
public static void main(String[] args) {
Runnable p1 = new PingPong("ping");
Thread t1 = new Thread(p1);
t1.start();
Runnable p2 = new PingPong("pong");
Thread t2 = new Thread(p2);
t2.start();
}
}
Output
ping0
pong0
I tried removing wait() and it's printing ping pong till the end of loop. but is this guaranteed that it will print in sequence?
Why wait() followed by notify() does not ask the ping1 thread to start execution?
If you see the jstack, you can see thread-0 and thread-1 are waiting for different lock. That's because your p1 and p2 are different objects, so when you use synchronized (this), they are not competing for the same lock, so notify this way won't work. try use another object as the lock.
wait need to run after notify. As when both threads go into waiting stat, no other threads can notify them.
try this code:
String word;
Object a;
public PingPong(String word, Object a) {
this.word = word;
this.a = a;
}
public void run() {
synchronized (a) {
for (int i = 0; i < 10; i++) {
System.out.println(word + i);
try {
a.notifyAll();
a.wait();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Object a = new Object();
Runnable p1 = new PingPong("ping", a);
Thread t1 = new Thread(p1);
t1.start();
Runnable p2 = new PingPong("pong", a);
Thread t2 = new Thread(p2);
t2.start();
}
Here is a similar solution using Thread Pool Executors:
public class PingPong implements Runnable {
String word;
Lock lock;
public PingPong(String word, Lock lock) {
this.word = word;
this.lock = lock;
}
#Override
public void run() {
while(true){
System.out.println("Received : " + word);
lock.notifyAll();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService ex = Executors.newFixedThreadPool(2);
Lock lock = new ReentrantLock();
while(true){
ex.submit(new PingPong("ping", lock));
ex.submit(new PingPong("pong", lock));
}
}
}
Below solution based on:
Java internal API
order of execution
public class Test {
public static void main(String[] args) {
SynchronousQueue<String> queue = new SynchronousQueue<>();
Thread ping = new Thread(new Task(queue, "ping", "ping"));
ping.setName("ping thread");
ping.start();
Thread pong = new Thread(new Task(queue, "pong", "ping"));
pong.setName("pong thread");
pong.start();
}
private static class Task implements Runnable {
private SynchronousQueue<String> queue;
private String command;
private String step;
Task(SynchronousQueue<String> queue, String command, String step) {
this.queue = queue;
this.command = command;
this.step = step;
}
#Override
public void run() {
try {
if (command.equals(step)) {
doCommandAndWaitRepeatedly();
} else {
waitAndDoCommandRepeatedly();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void doCommandAndWaitRepeatedly() throws InterruptedException {
while (true) {
queue.offer(command, 1, TimeUnit.SECONDS);
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + ":" + queue.poll(1, TimeUnit.SECONDS));
}
}
private void waitAndDoCommandRepeatedly() throws InterruptedException {
while (true) {
System.out.println(Thread.currentThread().getName() + ":" + queue.poll(1, TimeUnit.SECONDS));
Thread.sleep(500);
queue.offer(command, 1, TimeUnit.SECONDS);
}
}
}
}
class Ping extends Thread
{
public void run()
{
for(int i=1;i<=5;i++)
{
System.out.println("PING");
try{
sleep(2000);
} catch(Exception e){}
}
}
}
class Pong extends Thread
{
public void run()
{
for (int i=1;i<=5;i++)
{
System.out.println("PONG");
try{
sleep(2000);
} catch(Exception e){}
}
}
}
public class PingPong
{
public static void main(String... args) throws Exception
{
Ping p1=new Ping();
Pong p2=new Pong();
p1.start();
Thread.sleep(1000); //super important for proper sequence
p2.start();
p1.join();
}
}
Related
I have Counter class with 3 methods out of which 2 are synchronized, I want increment() to execute first and then the count(), so that count for each thread should always be 3000.
Instead of calling the count() from run() I can call it from within increment() is the only approach I can think of, Is there any other way to do So?
class Counter {
int count=0;
void print() {
System.out.println("Print called by: "+Thread.currentThread().getName());
}
synchronized void increment()
{
for(int i=1;i<=3000;i++)
count++;
}
synchronized void getCount() {
System.out.println(count);
count =0;
}
}
class MyThread1 extends Thread {
Counter c;
MyThread1(Counter c) {
this.c = c;
}
public void run() {
c.print();
c.increment();
c.getCount();
}
}
class MyThread2 extends Thread {
Counter c;
MyThread2(Counter c) {
this.c = c;
}
public void run() {
c.print();
c.increment();
c.getCount();
}
}
public class Demo {
public static void main(String args[]) {
Counter obj = new Counter();
MyThread1 t1 = new MyThread1(obj);
MyThread2 t2 = new MyThread2(obj);
t1.start();
t2.start();
}
}
Expected O/P in each case:
//The printing of "Print called by:" statement can be in any order as it's not synchronized but the count for each thread should always be 3000
Print called by: Thread-0
Print called by: Thread-1
3000
3000
Working example for my comment (You don't need MyThread1 and MyThread2):
public class Demo {
public static void main(String[] args) {
Counter obj = new Counter();
MyThread t1 = new MyThread(obj);
MyThread t2 = new MyThread(obj);
t1.start();
t2.start();
}
}
class Counter {
private final ThreadLocal<Integer> count = new ThreadLocal<Integer>() {
#Override
protected Integer initialValue() {
return 0;
}
};
void print() {
System.out.println("Print called by: " + Thread.currentThread().getName());
}
void increment() {
for (int i = 1; i <= 3000; i++)
count.set(count.get() + 1);
}
void getCount() {
System.out.println(count.get());
count.set(0);
}
}
class MyThread extends Thread {
Counter c;
MyThread(Counter c) {
this.c = c;
}
public void run() {
c.print();
c.increment();
c.getCount();
}
}
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo {
public static void main(String args[]) {
Counter obj = new Counter();
MyThread t1 = new MyThread(obj);
MyThread t2 = new MyThread(obj);
t1.start();
t2.start();
}
}
class Counter {
Lock lock = new ReentrantLock();
int count = 0;
void print() {
System.out.println("Print called by: " + Thread.currentThread().getName());
}
void increment() {
lock.lock();
for (int i = 1; i <= 3000; i++)
count++;
}
void getCount() {
System.out.println(count);
count = 0;
lock.unlock();
}
}
class MyThread extends Thread {
Counter c;
MyThread(Counter c) {
this.c = c;
}
public void run() {
c.print();
c.increment();
c.getCount();
}
}
You can use synchronized to block a thread.
here the example:
public void run() {
synchronized (Thread.class) {
c.print();
c.increment();
c.getCount();
}
}
synchronized needs an object as param, please use same object for both class MyThread1 and MyThread2
read https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html for more details.
In the example below if I implement ExecutorImpl without using Thread, then taskCompletionService.submit is blocked, even though it returns Future.
Is it possible to not block submit, but not use Thread in ExecutorImpl?
class ExecutorServiceTest {
private static class ExecutorImpl implements Executor {
public void execute(Runnable r) {
final Thread t = new Thread(new Runnable() {
public void run() {
r.run();
}});
t.start();
//If used will block others.
//r.run();
}
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
final Executor executor = new ExecutorImpl();
final CompletionService<String> taskCompletionService = new ExecutorCompletionService<>(executor);
int submittedTasks = 3;
for(int i = 0; i < submittedTasks; i++) {
final int j = i;
//here it is blocked if ExecutorServiceIml doesn't utilize Thread
taskCompletionService.submit(new Callable<String>() {
public String call() throws Exception {
Thread.sleep((3 - j) * 1000);
return "callable:" + String.valueOf(j);
}
});
System.out.println("Task " + String.valueOf(i) + " has been submitted...");
}
for(int tasksHandled=0; tasksHandled < submittedTasks; tasksHandled++) {
try {
final Future<String> result = taskCompletionService.take();
String l = result.get();
System.out.println("Task has completed - result: " + l);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
}
I'm writing a code simulating a race between multiple threads and print the winner of that race, the order of threads finished.
I was able to determine the winner, but I can't figure out how to print the order of all threads finished.
Here is the code till now, Any Help!!
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Runner {
private static CountDownLatch latch = new CountDownLatch(3);
private static String winner;
public static synchronized void finished(String threadName) {
if (winner == null) {
winner = threadName;
}
latch.countDown();
}
public static void main(String[] args) throws InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
threadPool.submit(new raceTrack("Racer "+i));
}
threadPool.shutdown();
threadPool.awaitTermination(1, TimeUnit.SECONDS);
try {
latch.await();
System.out.println("The winner is : " + winner);
}
catch (InterruptedException e) {
System.out.println("No winner");
Thread.currentThread().interrupt();
}
}
}
public class raceTrack implements Runnable {
public String racerID;
public raceTrack(String id) {
this.racerID = id;
}
#Override
public void run() {
System.out.println(racerID);
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
finally {
Runner.finished(racerID);
}
}
}
You can have a list of thread names instead of just one String:
private static List<String> threadList;
public static synchronized void finished(String threadName) {
threadList.add(threadName);
latch.countDown();
}
You then can iterate through the list and determine order of threads. The winner is determined as list.get(0)
please help me guys..
my observablelist was updated successfully by background Thread.
but my GUI Update is not accurate.
addPiechart1 to HBOX
addPieChart2 to HBOX
observablelist1= getobservablelist from piechart1
observablelist2= getobservablelist from piechart2
pass observablelist1 to Thread
pass observablelist2 to Thread
ex
on the process i call
animatePie(observablelist1,value1);
animatePie(observablelist2,value2);
public void animatePie(ObservableList<PieChart.Data> obs,int[] value){
ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactory() {
#Override public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
});
pieAddToQueue add = new pieAddToQueue(obs,value);
//add.run();
executor.execute(add);
}
private class pieAddToQueue implements Runnable {
ObservableList<PieChart.Data> observableData;
int[] value;
int loop;
public pieAddToQueue(ObservableList<PieChart.Data> obs,int[] value){
observableData=obs;
this.value=value;
loop=0;
}
#Override
public void run() {
for(int i=0;i<value.length;i++){
observableData.get(i).setPieValue(value[i]);
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(MISInfoBoardBottom.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
You cannot update the UI on a background thread, so you must wrap the calls that change the UI with a Platform.runLater(...):
private class pieAddToQueue implements Runnable {
ObservableList<PieChart.Data> observableData;
int[] value;
int loop;
public pieAddToQueue(ObservableList<PieChart.Data> obs,int[] value){
observableData=obs;
this.value=value;
loop=0;
}
#Override
public void run() {
for(int i=0;i<value.length;i++){
PieChart.Data pieChartData = observableData.get(i);
int v = value[i] ;
Platform.runLater(() ->
pieChartData.setPieValue(v));
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(MISInfoBoardBottom.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
I have been facing this problem for many days, Please help me out. I am implementing producer-consumer example using thread synchronization. I have made some twist in this traditional program. Instead of using only one queue object, i have used two Queue objects. But program is not working.. (PS- I know i can make this program work by using only one object of queue, But what if i want to use two queue objects ?? )
class Queue {
static int value;
static boolean valueSet = false;
public static final Object obj;
static {
obj = new Object();
}
void push() {
synchronized(Queue.obj) {
while( Queue.valueSet ) {
try {
Thread.sleep(1000);
}catch(Exception e) {}
}
System.out.print("\n\n Push:- " + (++(Queue.value)));
Queue.valueSet = true;
return;
}
}
void pop() {
synchronized(Queue.obj) {
while(!(Queue.valueSet)) {
try {
Thread.sleep(1000);
}catch(Exception e) {}
}
System.out.print("\n\n Pop:- " + Queue.value);
Queue.valueSet = false;
return;
}
}
}
class Producer implements Runnable {
Queue Q;
Thread P;
Producer(Queue Q) {
this.Q = Q;
P = new Thread(this);
P.start();
}
public void run() {
while(true) {
Q.push();
}
}
}
class Consumer implements Runnable {
Queue Q;
Thread C;
Consumer(Queue Q) {
this.Q = Q;
C = new Thread(this);
C.start();
}
public void run() {
while(true) {
Q.pop();
}
}
}
public class TestQueue {
public static void main(String[] args) {
Queue Q1 = new Queue();
Queue Q2 = new Queue();
Object obj = new Object();
Producer p = new Producer(Q1);
Consumer c = new Consumer(Q2);
}
}
I got the answer. My misconception was wait,notify and notifyall methods are of thread class. So i was invoking them on thread object.
Solution is to just invoke wait and notify method on shared static object other than thread.
Answer:-
class Queue {
static int value;
static boolean valueSet = false;
public static final Object obj;
static {
obj = new Object();
}
void push() {
synchronized(Queue.obj) {
while( Queue.valueSet ) {
try {
Queue.obj.wait();
Thread.sleep(1000);
}catch(Exception e) {
e.printStackTrace();
}
}
System.out.print("\n\n Push:- " + (++(Queue.value)));
Queue.valueSet = true;
Queue.obj.notify();
}
}
void pop() {
synchronized(Queue.obj) {
while(!(Queue.valueSet)) {
try {
Queue.obj.wait();
Thread.sleep(1000);
}catch(Exception e) {
e.printStackTrace();
}
}
System.out.print("\n\n Pop:- " + Queue.value);
Queue.valueSet = false;
Queue.obj.notify();
}
}
}
class Producer implements Runnable {
Queue Q;
Thread P;
Producer(Queue Q) {
this.Q = Q;
P = new Thread(this);
P.start();
}
public void run() {
while(true) {
Q.push();
}
}
}
class Consumer implements Runnable {
Queue Q;
Thread C;
Consumer(Queue Q) {
this.Q = Q;
C = new Thread(this);
C.start();
}
public void run() {
while(true) {
Q.pop();
}
}
}
public class TestQueue {
public static void main(String[] args) {
Queue Q1 = new Queue();
Queue Q2 = new Queue();
Producer p = new Producer(Q1);
Consumer c = new Consumer(Q2);
}
}