Java Shutdown Hook Issues - java

My shutdown hooks will not run. The shutdown hook is intended to print out statistics after the program has terminated for all philosopher threads that had been running. The philosopher class extends Thread, and simply chews and eats based on if forks are available or not. Here is my code.
public class Main {
private static ArrayList<Philosopher> philosophers = new ArrayList<Philosopher>();
public static void main(String[] args) {
int counter = 0;
int num = Integer.parseInt(args[0]); // number of philosopher threads to create
for(int x = 0; x < num; x++)
{
Fork one = new Fork(counter);
counter++;
Fork two = new Fork(counter);
counter++;
Philosopher p = new Philosopher(String.valueOf(x), one, two); // (Identifier, fork one, fork two)
philosophers.add(p);
}
// Create shutdown hook
Stats s = new Stats(philosophers);
Runtime.getRuntime().addShutdownHook(s);
// Start all philosopher threads
for(Philosopher phil : philosophers)
{
phil.start();
}
}
}
public class Stats extends Thread{
private ArrayList<Philosopher> list = new ArrayList<Philosopher>();
public Stats(ArrayList<Philosopher> al)
{
list = al;
}
public void run()
{
System.out.println("Test");
for(Philosopher p : list)
{
System.out.println(p.getPhilName() + " thought for " + p.getTimeThinking() + " milliseconds and chewed for " + p.getTimeChewing() + " milliseconds.");
}
}
}
Thanks for any help you can provide, I greatly appreciate it.

You're creating Philosopher instances but are not adding them to list, hence the list remains empty and your shut-down hook appears not to run because it won't print anything to stdout.
EDIT
Following your recent comment the next thing I'd suggest is to add logging to prove that all threads are terminating. For example, you could join with each philosopher thread from your main thread so that when your main thread terminates you are certain that each philosopher thread has previously terminated.
// Start all philosopher threads
for (Philosopher phil : philosophers) {
phil.start();
}
for (Philosopher phil : philosophers) {
System.err.println("Joining with thread: " + phil.getName());
phil.join();
}
System.err.println("Main thread terminating.");
// Shut-down hook should now run.
}

Related

How to ensure execution order of threads [duplicate]

This question already has answers here:
How threads are executed in the memory?
(2 answers)
Closed 2 years ago.
This is a simplified version of the problem. Given n number of threads, each printing a constant number all the time. For example, Thread-1 should always print 1, Thread-2 should always print 2 and so on...
How to ensure, the threads are executed in order i.e. the output should be as below:
Thread-1: 1
Thread-2: 2
Thread-3: 3
.
.
.
Thread-n: n
I have a naïve solution to do it through wait()/notify() but I guess there might be a better solution than that. Perhaps, using Semaphore maybe? I don't know.
Update:
Based on the answers received, I think I was not very clear. There are some constraints:
All threads should start at once (assume we don't really have control on that)
Once all the threads start, there should be some sort of communication between the threads to execute in order.
This sequentially execution of thread can be handled beautifully using Thread.join() method. To handle it properly, you may have to create MyRunnable(or, use any name you prefer) which implements Runnable interface. Inside MyRunnable, you can inject a parent Thread, and call parent.join() at top of MyRunnable.run() method. The code is given below:
public class SequentialThreadsTest {
static class MyRunnable implements Runnable {
static int objCount; // to keep count of sequential object
private int objNum;
private Thread parent; // keep track of parent thread
MyRunnable(Thread parent) {
this.parent = parent;
this.objNum = objCount + 1;
objCount += 1;
}
#Override
public void run() {
try {
if(parent != null) {
parent.join();
}
System.out.println("Thread-" + objNum + ": " + objNum);
} catch(InterruptedException e) {
e.printStackTrace();
// do something else
} finally {
// do what you need to do when thread execution is finished
}
}
}
public static void main(String[] args) {
int n = 10;
Thread parentThread = null;
for(int i=0; i<n; i++) {
Thread thread = new Thread(new MyRunnable(parentThread));
thread.start();
parentThread = thread;
}
}
}
And the output is:
Thread-1: 1
Thread-2: 2
Thread-3: 3
Thread-4: 4
Thread-5: 5
Thread-6: 6
Thread-7: 7
Thread-8: 8
Thread-9: 9
Thread-10: 10
You haven't specified many details, but if you only want serializable thread execution you can wait for previous thread to finish and then print. Something like this:
public static void main(String[] args) {
Thread thread = null;
for (int i = 0; i < 10; i++) {
int index = i;
Thread previousThread = thread;
thread = new Thread(() -> {
if (previousThread != null) {
try {
previousThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(index);
});
thread.start();
}
}
Try making a queue - this will do exactly what you want. Simply change the value of n to however many threads you have, and add all the threads sequentially (only once). If ever you want to stop the threads from executing, all you have to do is add end to the queue. Obviously, for a larger project, you will need to modify this code a little bit (I would recommend replacing the main method with a class initializer and pass the LinkedBlockingQueue as a pre-built argument)
import java.util.concurrent.LinkedBlockingQueue;
public class HelloWorld{
private static int n = 2;
private static LinkedBlockingQueue<Thread> queue = new LinkedBlockingQueue<>(n+1);
static Thread a = new Thread(()->{
System.out.print("a");
});
static Thread b = new Thread(()->{
System.out.print("b");
});
static Thread end = new Thread(()->{
break_ = true;
});
public static final int END = 20;//this and the counter are just here so the code doesn't run forever
public static volatile int i = 0;
public static volatile boolean break_ = false;
public static void main(String []args){
queue.add(a);
queue.add(b);
//queue.add(end);
outerloop:
while(true){
Thread toBeRun = queue.poll();
try{
toBeRun.run();
queue.add(toBeRun);
i++;
if(i>=END || break_){//i>=END does not need to be here, it's just to stop it from running forever in this example
break;
}
}catch(NullPointerException e){
break;
}
}
}
}
Note: This uses java 8 lambdas. If you're using an older version of java, you will need to create the threads using the run method.

Java concurrency using ConcurrentHashMap with synchronized block

Here is my main class that initializes and starts 5 different Threads:
public class Server implements Runnable {
Server1 server1;
Thread server1Thread;
public Server() {}
#Override
public void run() {
server1 = new Server1();
server1Thread = new Thread(server1);
server1Thread.start();
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
Server s = new Server();
s.run();
}
}
}
Here is my Server1 Runnable:
import java.util.concurrent.ConcurrentHashMap;
public class Server1 implements Runnable {
private ConcurrentHashMap<Integer, Integer> storage= new ConcurrentHashMap<>();
public Server1() {}
#Override
public void run() {
synchronized (this){
for (int i = 0; i < 10; i++) {
storage.put(i, (int)(Math.random()*100));
}
for (int i : storage.keySet()) {
System.out.print("(" + i + "," + storage.get(i) + ") ");
}
System.out.println();
}
}
}
It puts in ConcurrentHashMap storage keys from 0 to 9 and assigns them a random value between 0 and 100. After that it prints it and prints new line at the end. I have user synchronized block to make sure the thread itself access keys correctly but it prints something like this:
(0,8) (0,87) (1,60) (1,14) (2,20) (2,70) (3,5) (0,74) (0,42) (1,22) (4,96) (0,85) (1,97) (2,75) (3,68) (4,3) (5,49) (6,3) (7,9) (8,47) (9,52)
(3,2) (5,74) (2,86) (1,48) (3,5) (6,0) (4,0) (7,86) (4,22) (8,20) (2,17) (9,87)
(5,96) (5,15) (6,15) (6,92) (7,48) (8,93) (9,67)
(3,87) (7,43) (4,34) (5,48) (8,91) (9,64)
(6,84) (7,75) (8,47) (9,87)
which obviously means that some thread prints more that 10 keys that I assigned to it. How do I make every thread print exactly 10 keys and values that it is assigned to them and ensure concurrency here?
I am not sure how to test it.
Your threads don't share any internal state. They're working fine, but the output is interleaved.
For instance if you used a StringBuilder to do the I/O in one operation, you should see correct output.
StringBuilder buff = new StringBuilder();
for (int i : storage.keySet()) {
buff.append("(" + i + "," + storage.get(i) + ") ");
}
System.out.println(buff);
There is no good reason for Server to be Runnable, or even to create any instances of it.
You do not share any of the maps. If you did, then you would also want to share a common lock, but this is not the usual way to use ConcurrentMap.
All you had to do was synchronized (Server1.class) as that is common across threads. Not the instance
Here is the verified output:
(0,75) (1,9) (2,61) (3,73) (4,55) (5,34) (6,34) (7,74) (8,41) (9,0)
(0,30) (1,42) (2,46) (3,66) (4,12) (5,17) (6,62) (7,59) (8,74) (9,4)
(0,50) (1,16) (2,29) (3,74) (4,68) (5,42) (6,33) (7,91) (8,25) (9,7)
(0,49) (1,10) (2,39) (3,94) (4,12) (5,55) (6,54) (7,89) (8,21) (9,75)
(0,77) (1,10) (2,37) (3,32) (4,73) (5,39) (6,64) (7,98) (8,96) (9,44)

Something wrong with the Peterson algorithm logic?

I am pretty new to Multithreading programming. In my code threads are trying to acquire locks around few lines. The lines work pretty fine for few context switches but then it halts (probably a deadlock).
On the other hand if use synchronized block then all works fine.
I've four classes.
1. PetersonAlgorithm.java
package com.ashish.master;
public class PetersonAlgorithm {
boolean wantCS[] = {false, false};
int turn = 1;
public void requestCS(int i) {
System.out.println("Lock requested by the thread - " + i);
wantCS[i] = true;
turn = 1 - i;
while(wantCS[1-i] && turn == 1-i);
}
public void releaseCS (int i) {
wantCS[i] = false;
turn = i - 1;
System.out.println("Lock released by the thread - " + i);
}
}
If anyone feels that above algorithm is incorrect then let me know, and feel free to make suggestions.
2. Runner.java
package com.ashish.master;
public class Runner {
public static Incrementer runnableInstance = new Incrementer();
public static Thread inc1 = new Thread(runnableInstance, "0");
public static Thread inc2 = new Thread(runnableInstance, "1");
public static void main(String args[]) {
inc1.start();
inc2.start();
try{
inc1.join();
inc2.join();
} catch (InterruptedException ex) {
System.out.println("The threads have been interrupted while waiting for the join ---> " + ex.getMessage());
}
System.out.println("The total turns taken by incrementer are ----> " + runnableInstance.turns);
}
}
3. Incrementer.java - If synchronized block is used instead of the Peterson algorithm, everything works fine.
package com.ashish.master;
public class Incrementer implements Runnable {
public long turns = 0;
public PetersonAlgorithm pa = new PetersonAlgorithm();
#Override
public void run() {
System.out.println("Thread " + this.toString() + "started.....");
while(true) {
pa.requestCS(Integer.parseInt(this.toString()));
// synchronized(this) {
if(DataStore.data < 1000000) printCriticalSection();
else break;
// }
pa.releaseCS(Integer.parseInt(this.toString()));
}
}
public void printCriticalSection() {
System.out.println("The value of the number is increased by thread " +
this.toString() +" to --> " + DataStore.increase());
turns ++;
}
#Override
public String toString() {
return Thread.currentThread().getName();
}
}
4. DataStore.java A class to mock the data source -- simply increase the number
package com.ashish.master;
public class DataStore {
public static long data = 0L;
public static long increase() {
DataStore.data += 1;
return DataStore.data;
}
}
Your runnables never observe each other's monitors (wantCS and turn) as they have different instances... Each runnable needs to work with a same shared set of monitors!
Take the blue pill and make your PetersonAlgorithm variables static volatile with synchronized block access...
Or take the red pill and you create a Class for your flag monitors (wantCS) and for your indicator monitor (turn). Then just define your runnable with one "own flag", one "observed flag" and one "indicator". Both Runnables will have the same indicator instance (therefore needs to be synchronized) while the flag instances will be crossed (the own flag of R1 will be the observed flag of R2 and the own flag of R2 the observed flag of R1). You should synchronized the flag methods too as you don't want to have a flag raised or lowered while being observed.
Then few steps:
Runnables raise their Flag
Runnables turn the shared Indicator ( set to opponent runnable's id )
Wait if opponent's flag is raised and Indicator is set to opponent.
The non waiting opponent does its stuff then lowers its flag.
The waiting opponent stops waiting (opponent's flag has been lowered), does its stuff and lowers its flag.
Each of your runnable instances has its own PetersonAlgorithm instance. Thus, the two runnables don't know anything about each other and will both always get immediate access to the critical section. Try implementing your PetersonAlgorithm class as static class with static methods. Then change the lines
pa.requestCS(Integer.parseInt(this.toString()));
// ...
pa.releaseCS(Integer.parseInt(this.toString()));
into
PetersonAlgorithm.requestCS(Integer.parseInt(this.toString()));
// ...
PetersonAlgorithm.releaseCS(Integer.parseInt(this.toString()));

Synchronizing threads

So I have a code:
public void runThreads(int number)
{
List<Thread> threadList = new ArrayList<Thread>();
for (int i = 0; i < number; i++)
{
Thread t = new MyThread(getRandomPerson(),i);
threadList.add(t);
}
for (Thread x : threadList)
{
x.start();
}
}
So I am adding threads to my list of threads and then starting this threads.
This is MyThread class:
public class MyThread extends Thread
{
Person person;
int number;
public MyThread(Person person, int number)
{
this.person = person;
this.number = number;
}
#Override
public void run()
{
try
{
synchronized (this)
{
Thread.sleep(1000);
System.out.println(number + "\t" + person.getSurname());
Thread.sleep(1000);
System.out.println(number + "\t" + person.toString());
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
I wanted to make a program which creates the threads, adds them to the list, invokes them but each thread should wait until the previous ended its task.
So output should be like :
1 Surname
/** Waitning second */
1 person.toString()
/** Waiting second*/
And then the second thread start invoking:
2 Surname
....
How to achieve this using synchronized? I tried different ways to use synchronized but it failed.
public class MyThread extends Thread
{
private static Object lock = new Object();
...
synchronized (lock)
{
Thread.sleep(1000);
System.out.println(number + "\t" + person.getSurname());
Thread.sleep(1000);
System.out.println(number + "\t" + person.toString());
}
...
That way you will get the same person's surname and toString() in order. You won't enforce strict ordering on the people, person 7 may still go before person 1.
You need a common lock - at the moment you are synchronizing on this, which is different for each thread. Try something like:
private static final Object lock = new Object();
and synchronize on that static (therefore shared) variable instead.
If you must use threads and if you must have order of execution, then you can do a t.join() immediately after t.start() - this will ensure the following flow:
- Main Thread
- loop
- start child thread
- wait for child thread to finish
- continue loop
- Exit Main thread
But, as pointed before, you don't need threads to do this since you can see that there is absolutely no gain from this approach (apart from academical) and it's detrimental in fact.
And special thanks to #assylias.

cachedThreadPool not working as I expected

I'm playing around with threads and I don't understand why this isn't working as I thought.
I am trying to calculate a sum using threads and was expecting for the thread pool to wait for all tasks to finish by the time I print out the result (due to the shutdown() call and the isTerminated() check).
What am I missing here?
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test5 {
private Integer sum= new Integer(0);
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
Test5 obj = new Test5();
for(int i=0; i<1000; i++){
pool.execute(obj.new Adding());
}
pool.shutdown();
while(!pool.isTerminated()) {
//could be empty loop...
System.out.println(" Is it done? : " + pool.isTerminated());
}
System.out.println(" Is it done? : " + pool.isTerminated());
System.out.println("Sum is " + obj.sum);
}
class Adding implements Runnable {
public void run() {
synchronized(this) {
int tmp = sum;
tmp+=1;
sum=new Integer(tmp);
}
}
}
}
While I do get good results, I also get output such as this:
Is it done? : true
Sum is 983
You need to sync on the main object instance. I'm using int below, Integer will work too (needs to initialized to zero explicitly).
Here is the working code
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class AppThreadsSum {
int sum;
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
AppThreadsSum app = new AppThreadsSum();
for (int i = 0; i < 1000; i++) {
pool.execute(app.new Adding());
}
pool.shutdown();
while (!pool.isTerminated()) {
System.out.println(" Is it done? : " + pool.isTerminated());
}
System.out.println(" Is it done? : " + pool.isTerminated());
System.out.println("Sum is " + app.sum);
}
class Adding implements Runnable {
public void run() {
synchronized (AppThreadsSum.this) {
sum += 1;
}
}
}
}
p.s. Busy waiting is an anti-pattern to be avoided (copied from the neighbor answer to be complete and aware of this important thing, see comments)
You have a number of issues.
Your code is not threadsafe
Busy waiting is an anti-pattern to be avoided.
What do i mean by 1.?
Lets suppose we have two threads, A & B.
A reads sum into tmp as 1
B reads sum into tmp as 1
A increments sum to 2
A writes sum as 2
B increments sum to 2
B writes sum as 2
So we end up with 2 after two increments. No quite right.
Now you may say "but I have used synchronized, this should not happen". Well, you haven't.
When you create your Adding instances you new each one. You have 1000 separate Adding instances.
When you synchronized(this) you are synchronizing on the current instance, not across all Adding. So your synchronized block does nothing.
Now, the simple solution would be to use synchronized(Adding.class).
The synchronized(Adding.class) will make the code block synchronized correctly across all Adding instances.
The good solution would be to use an AtmoicInteger rather than an Integer as this increments atomically and is designed for exactly this sort of task.
Now onto 2.
You have a while(thing){} loop, this basically runs the thread like crazy testing thousands of times a millisecond until thing is true. This is a huge waste of CPU cycles. An ExecutorService has a special, blocking, method that waits until it has shutdown, awaitTermination.
Here is an example:
static final AtomicInteger sum = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < 1000; i++) {
pool.execute(new Adding());
}
pool.shutdown();
pool.awaitTermination(1, TimeUnit.DAYS);
System.out.println(" Is it done? : " + pool.isTerminated());
System.out.println("Sum is " + sum);
}
static class Adding implements Runnable {
public void run() {
sum.addAndGet(1);
}
}
I would also suggest not using a cachedThreadPool in this circumstance as you have 1000 Runnables being submitted and this will generate far more Threads than you have CPUs. I would suggest using newFixedThreadPool with a sane number of Threads.
I'm not even going to go into the use of int literals and Integer and why new Integer() is not needed.

Categories