ShutDownHook in multi-threaded application - java

I have an application which in its main method spawns a hundred threads (let's say we simulate a hundred accounts). I am experimenting with it and I would like it to just print terminating when intterupted with Control-C.
I read you can do that with ShutDownHooks so I added the following in my main method:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("Terminating");
}
});
However, when I run it nothing gets printed.
Could you please offer me some guidance as to where I am going wrong (all threads are declared in a for loop and start with invoking their start method)?
Regards,
George
EDIT: Please see below for the code:
Bank Class:
public class Bank {
private final double[] accounts;
public Bank(int n, double initialBalance) {
accounts = new double[n];
for (int i=0; i < accounts.length;i++) {
accounts[i] = initialBalance;
}
}
public double getTotalBalance() {
double sum = 0.0;
for (int i=0; i < accounts.length; i++) {
sum += accounts[i];
}
return sum;
}
public synchronized void transfer(int fa, int ta, double amt) throws InterruptedException{
System.out.print(Thread.currentThread());
if (accounts[fa] < amt){
wait();
}
accounts[ta] -= amt;
System.out.println("Transfer of amount: " + amt + " from: " + fa + " Transfer to: " + ta);
accounts[fa] += amt;
System.out.println("Total Balance: " + getTotalBalance());
notifyAll();
}
public int size() {
return accounts.length;
}
public double[] getAccounts(){
return accounts;
}
}
BankTest Class:
public class BankTest {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Bank b = new Bank(100,1000);
int i;
long timeStart = System.currentTimeMillis();
long j = System.currentTimeMillis();
for (i=0; i < b.size(); i++) {
TransferRunnable tr = new TransferRunnable(b, i, 1000,j);
Thread t = new Thread(tr);
t.start();
}
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("Terminating");
}
});
}
}
TransferRunnable Class:
public class TransferRunnable implements Runnable {
private Bank b;
private int fromAccount;
private double maxAmount;
private final int DELAY = 40;
private long timeStart;
public TransferRunnable(Bank b, int from, double max, long timems) {
this.b = b;
fromAccount = from;
maxAmount = max;
timeStart = timems;
}
#Override
public void run() {
try {
while (true) {
int ta = (int) (b.size() * Math.random());
double amount = maxAmount * Math.random();
double[] acc = b.getAccounts();
b.transfer(fromAccount,ta,amount);
Thread.sleep((int) (DELAY*Math.random()));
}
}
catch (InterruptedException e) {
}
}
}

It gets printed when I run it. You could add System.out.flush(); to the end of the run() method though, this makes sure that the output is printed immediately.

as others have said, this should just work. What OS are you using? It might be that CTRL+C is killing the process completely rather than asking it to shutdown (eg SIGKILL vs SIGINT). Can you verify which signal you're sending the Java process?
Finally, as a last resort you could try the following bit of Java:
if (FileDescriptor.out.valid()) {
FileDescriptor.out.sync();
}
I suspect that this won't make any difference though!

Related

Programme not Terminating in Multi-threaded environment -Java

Trying to make a simple multi-threaded programme where it prints Factorial series where each number is printed by different Thread and at the end I am giving a report of which number printed by which thread.I have got the desired output but somehow my program is not terminating.
Constraint: I am not allowed to use Concurrent Package
import java.util.ArrayList;
import java.util.Scanner;
class Report {
private long factorial;
private String threadName;
private int activeThreads;
public Report(long factorial, String threadName, int activeThreads) {
this.factorial = factorial;
this.threadName = threadName;
this.activeThreads = activeThreads;
}
public long getFactorial() {
return factorial;
}
public String getThreadName() {
return threadName;
}
public int getActiveThreads() {
return activeThreads;
}
public void setActiveThreads(int activeThreads) {
this.activeThreads = activeThreads;
}
}
public class Factorial implements Runnable {
public static ArrayList<Report> report = new ArrayList<Report>();
private static int count;
public static void main(String[] args) throws InterruptedException {
Scanner in = new Scanner(System.in);
System.out.print("N: ");
int n = in.nextInt();
count = n;
Factorial f = new Factorial();
f.series(n);
Thread.sleep(1000);
// Series
for(Report r : report) {
if(r.getFactorial() == 1) {
System.out.print(r.getFactorial());
}
else {
System.out.print(r.getFactorial() + "*");
}
}
System.out.println();
// Report
for(Report r : report) {
System.out.println(r.getFactorial() + " printed by " + r.getThreadName() + " " + r.getActiveThreads());
}
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
System.out.println("In Main");
in.close();
}
public void series(int n) throws InterruptedException {
for(int i=0;i<n;i++) {
Thread t = new Thread(new Factorial());
t.start();
}
}
public synchronized void generate() {
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
report.add(new Report(count--, Thread.currentThread().getName(), threadGroup.activeCount()));
notifyAll();
System.out.println("In generate" + threadGroup.activeCount());
}
#Override
public void run() {
generate();
synchronized (this) {
try {
wait();
}
catch(Exception e) {
e.printStackTrace();
}
}
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
System.out.println("In Run" + threadGroup.activeCount());
}
public static int getCount() {
return count;
}
public static void setCount(int count) {
Factorial.count = count;
}
}
Although I know that we can kill the threads using .stop() but I think it's not recommended.
To make synchronization effective (synchronized, wait, notify), you have to use the same instance.
In series, you create a new Factorial instance on each loop, making every thread to wait indefinitely.
public void series(int n) throws InterruptedException {
for(int i=0;i<n;i++) {
// Thread t = new Thread(new Factorial()); // creates an new instance
Thread t = new Thread(this);
t.start();
}
}
In the run method, you first call notifyAll() (through generate), and then wait.
The last created thread will wait after all the others are done.
One way or another, this last thread has to be notified.
It could be right after the sleep call, with:
synchronized(f) {
f.notify();
}
or maybe with a dedicated synchronized method.

Java Multithreading two classes in main

I am very new to programming, and I am trying to write a Java program with the Timer and ChecksUserInput classes shown below. How do I get them to run at the same time in the main class?
I am also having issues with printing out the word length in ChecksUserInput.
main.java:
package application;
public class Main {
public static void main(String[] args) {
CreateBoard board = new CreateBoard();
board.run();
Timer timer = new Timer();
timer.run();
ChecksUserInput input = new ChecksUserInput();
input.run();
}
}
timer.java:
package application;
public class Timer {
private static void time() {
final int mili = 1000;
final int sec = 60;
final int oneMinute = (mili * sec);
System.out.println("Start 3 minute timer");
sleep(oneMinute * 2);
System.out.println("One minute remaining...");
sleep(oneMinute);
System.out.println("Time's up!");
}
private static void sleep(int sleepTime) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
time();
}
}
checksuserinput.java:
package application;
import java.util.*;
public class ChecksUserInput {
private static String UserInput() {
Scanner sc = new Scanner(System.in);
System.out.println("Begin entering words!");
String word = null;
for (int i = 0; i < 10000; i++) {
word = sc.nextLine();
}
return word;
}
private static int length(String word) {
int wordLength = word.length();
return wordLength;
}
public void run() {
String userWord = UserInput();
int wordLength = length(userWord);
System.out.println(wordLength);
}
}
The foundation of multi-threading in Java is the Thread class. The general structure for usage is:
Thread newProcess = new Thread(processToRun); //Create a thread which will execute the process
newProcess.setDaemon(true/false); //when false, the thread will keep the JVM alive beyond completion of 'main'
newProcess.start(); //Start processToRun in a new thread
To start several independent processes, this should be sufficient. For example, the following starts 10 threads each of which will print the index in the loop. At the end, the process sleeps for 5 milliseconds because the spawned threads are daemon. Removing this may cause the process to terminate before any messages are printed.
public static void main(String args[]) throws Exception
{
for(int i = 0; i < 10; i++) { int index = i; start(() -> System.out.println(index)); }
Thread.sleep(5);
}
public static void start(Runnable processToRun)
{
Thread newProcess = new Thread(processToRun);
newProcess.setDaemon(true);
newProcess.start();
}
Beyond this point questions start to get more complicated/contextual. Ex:
How can processes running in 2 threads communicate with each other?
How can processes running in 2 threads access/modify common state between them?
In the context of creating a simple game, one option is to use Queues to feed user inputs to the game and have the game process updates in a single thread. The following sample listens for the user inputting commands (Up, Down, Left, Right) on the main thread and adds valid commands to a queue. Valid commands are polled and processed in a different thread to update the location on the board.
Sample:
public static void main(String args[])
{
Board board = new Board();
BlockingQueue<Move> movesQueue = new ArrayBlockingQueue<>(100);
Scanner systemListener = new Scanner(System.in);
start(() -> routeBoardMovesToQueue(board, movesQueue)); /*route moves from the queue to the board in a new thread*/
while(true)
{
Optional<Move> nextMove = Move.resolve(systemListener.nextLine());
if(nextMove.isPresent())
movesQueue.offer(nextMove.get()); /*Write moves from System.in to the queue*/
else
System.out.println("Invalid Move Provided");
}
}
public static void routeBoardMovesToQueue(Board board, BlockingQueue<Move> movesQueue)
{
try
{
while(true)
{
Move next = movesQueue.poll(100_000, TimeUnit.DAYS);
if(next != null) board.performMove(next);
}
}
catch(InterruptedException ignored){ System.out.println("Stopping"); }
}
public static void start(Runnable processToRun)
{
Thread newProcess = new Thread(processToRun);
newProcess.setDaemon(true);
newProcess.start();
}
public static final class Board
{
private final Location location;
public Board(){ this.location = new Location(); }
public void performMove(Move move)
{
switch(move)
{
case Up: location.y += 1; break;
case Down: location.y -= 1; break;
case Right: location.x += 1; break;
case Left: location.x -= 1; break;
}
System.out.println("New Position: (" + location.x + ", " + location.y + ")");
}
public static class Location{ int x = 0; int y = 0; }
}
public enum Move
{
Up, Down, Left, Right;
public static Optional<Move> resolve(String move){ return Stream.of(Move.values()).filter(mv -> Objects.equals(move, mv.name())).findAny(); }
}
You should search "java multithreading" on your favourite search engine and compare your code with those examples
You will find that these people have (mostly) implemented the Runnable interface on their classes.
So
-- public class ChecksUserInput {
++ public class ChecksUserInput implements Runnable{
And run() was a method of that interface, that they had to implement.
Your version first runs the run method of the first class, then the other.
But when you implement the runnable interface, the both run methods will be called right after one another, without waiting for the first one to finish
You should search on your own and find more examples, or check the documentations for multithreading if you face any other issues
So after the wonderful help #BATIKAN BORA ORMANCI and #mike1234569 gave me along with this link https://www.geeksforgeeks.org/multithreading-in-java/ I was able to actually figure it out
package application;
public class Main {
public static void main(String[] args) {
CreateBoard board = new CreateBoard();
board.run();
Thread timer = new Thread(new Timer());
Thread input = new Thread(new ChecksUserInput());
timer.start();
input.start();
try {
timer.join();
input.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
and I set my classes to implement Runnable as Batikan suggested

synchronize concept in java doesn't work?

We have one hundred accounts in the bank and two clerks, implemented as threads, who transfer each 1000 times money from account with number accountNumberFrom to account accountNumberTo, using the synchronized method transferMoney. Since all accounts start with balance 0 and the money retrieved from one account is transferred to another, the balance should be zero after all the transactions. This is true most of the time, but not always. Although it occurs seldom, but sometimes the balance after the transactions is not equal to 0. What is wrong?
public class Clerk extends Thread {
private Bank bank;
public Clerk(String name, Bank bank) {
super(name);
this.bank=bank;
start();
}
public void run() {
for (long i=0; i<1000; i++) {
int accountNumberFrom = (int) (Math.random()*100);
int accountNumberTo = (int) (Math.random()*100);
float amount = (int) (Math.random()*1000) - 500;
bank.transferMoney(accountNumberFrom, amount);
bank.transferMoney(accountNumberTo, -amount);
}
}
}
and a class Bank
public class Bank {
Account[] account;
public Bank() {
account = new Account[100];
for (int i=0; i < account.length; i++)
account[i] = new Account();
}
public synchronized void transferMoney(int accountNumber, float amount) {
float oldBalance = account[accountNumber].getBalance();
float newBalance = oldBalance + amount;
account[accountNumber].setBalance(newBalance);
}
}
public class Banking {
public static void main (String[] args) {
Bank myBank = new Bank();
/**
* balance before transactions
*/
float sum=0;
for (int i=0; i<100; i++)
sum+=myBank.account[i].getBalance();
System.out.println("before: " + sum);
new Clerk ("Tom", myBank);
new Clerk ("Dick", myBank);
/**
* balance after transactions
*/
for (int i=0; i<100; i++)
sum+=myBank.account[i].getBalance();
System.out.println("after: " + sum);
}
}
One issue is that the synchronized transferMoney method only takes one account and so it's possible another thread could access the account balances after the transfer amount has been added to the "to" account but before it has been deducted from the "from" account. If all accounts start at zero, we could have this sequence of events:
Clerk Tom adds $100 to account 1.
Main thread totals account balances.
Clerk Tom deducts $100 from account 2.
At step 2 we see that the total of all accounts is $100 instead of zero.
So it's important that the transferMoney method update both accounts while holding the synchronized lock.
Another issue is that while the transferMoney is synchronized, the code that totals the account balances (step 2 above) is not. So even if you update both accounts in the transferMoney method, the sequence of events above can still happen because the main thread doesn't synchronize before executing step 2.
I would move the code that totals up the accounts to Bank and make it synchronized too. That will make both methods synchronized on the Bank instance and prevent the sequence of events that gives the wrong error.
A secondary issue is that in the main thread, you don't wait for the clerks to finish their transfers. Your code is performing all 1,000 transfers, but you just check the balances right after you start the clerk threads, so you may be looking at the balances after 0 transfers, or after all 1,000, or after 639 transfers, who knows. Doing the synchronization correctly will prevent you from seeing a non-zero total balance, but you should still wait for the clerks to finish. (Give it a try and if you can't figure it out, post a new question.)
In your example synchronized only block all thread call to myBank.transferMoney, but it doesn't ensure every threads done on main thread, you can update source code like this:
class Clerk extends Thread {
private Bank bank;
private volatile boolean done;
public Clerk(String name, Bank bank) {
super(name);
this.done = false;
this.bank=bank;
start();
}
public void run() {
for (long i=0; i<1000; i++) {
int accountNumberFrom = (int) (Math.random()*100);
int accountNumberTo = (int) (Math.random()*100);
float amount = (int) (Math.random()*1000) - 500;
bank.transferMoney(accountNumberFrom, amount);
bank.transferMoney(accountNumberTo, -amount);
}
this.done = true;
}
public boolean isDone() {
return done;
}
}
class Account {
protected float balance;
public float getBalance() {
return balance;
}
public void setBalance(float newBalance) {
this.balance = newBalance;
}
}
class Bank {
Account[] account;
public Bank() {
account = new Account[100];
for (int i=0; i < account.length; i++)
account[i] = new Account();
}
public synchronized void transferMoney(int accountNumber, float amount) {
float oldBalance = account[accountNumber].getBalance();
float newBalance = oldBalance + amount;
account[accountNumber].setBalance(newBalance);
}
}
public class Banking {
public static void main (String[] args) throws Exception {
for(int j = 0 ; j < 1000 ; ++j) {
Bank myBank = new Bank();
/**
* balance before transactions
*/
float sum=0;
for (int i=0; i<100; i++)
sum+=myBank.account[i].getBalance();
System.out.println("before: " + sum);
Clerk a = new Clerk ("Tom", myBank);
Clerk b = new Clerk ("Dick", myBank);
while(!a.isDone() || !b.isDone()) // wait util all thread done
Thread.sleep(1);
/**
* balance after transactions
*/
for (int i=0; i<100; i++)
sum+=myBank.account[i].getBalance();
System.out.println("after: " + sum);
}
}
}
Thanks a lot for the helpful answers. I modified my code and now it is working as it should:
public class Bank
{
Account[] account;
public Bank() {
account = new Account[100];
for (int i=0; i < account.length; i++)
account[i] = new Account();
}
public void transferMoney(int accountNumber, float amount) {
synchronized (account[accountNumber]) {
float oldBalance = account[accountNumber].getBalance();
float newBalance = oldBalance - amount;
account[accountNumber].setBalance(newBalance);
}
}
}
public class Account {
private float balance;
public void setBalance(float balance) {
this.balance=balance;
}
public float getBalance() {
return this.balance;
}
}
public class Clerk extends Thread {
private Bank bank;
public Clerk(String name, Bank bank) {
super(name);
this.bank=bank;
}
public void run() {
for (long i=0; i<100; i++) {
int accountNumberFrom = (int) (Math.random()*100);
int accountNumberTo = (int) (Math.random()*100);
float amount = (int) (Math.random()*1000);
bank.transferMoney(accountNumberFrom, -amount);
bank.transferMoney(accountNumberTo, amount);
}
}
}
public class Accountant extends Thread
{
Bank bank;
public Accountant(String name, Bank bank)
{
super(name);
this.bank=bank;
}
#Override public void run() {
getBalance();
}
public synchronized void getBalance() {
float sum=0;
System.out.println(Thread.currentThread().getName());
for (int i=0; i<100; i++)
sum+=bank.account[i].getBalance();
System.out.println("Bilanz: " + sum);
}
}
public class Banking {
public Banking() {
}
public static void main(String[] args) {
Bank myBank = new Bank();
Clerk tom = new Clerk ("Tom", myBank);
Clerk dick = new Clerk ("Dick", myBank);
Accountant harry = new Accountant("Harry", myBank);
tom.start();
dick.start();
try {
System.out.println("Current Thread: " + Thread.currentThread().getName());
tom.join();
dick.join();
}
catch(Exception x) {
System.out.println("Exception has " + "been caught" + x);
}
harry.start();
}
}

Another way to perform multithreading than using static method and variable

I'm writing a program that starts 1000 threads, each thread adds 1 to a variable sum. here's the code:
public class Test1 implements Runnable{
public Test1( ) {
}
public void run() {
Sum.sum++;
}
public static void main(String[] args) {
//Sum s = new Sum();
for (int i = 0; i < 1000; i++) {
Thread t = new Thread(new Test1());
try {
t.start();
t.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Sum.getSum());
}
}
public class Sum {
static int sum;
public Sum() {
sum = 0;
}
public static int getSum() {
return sum;
}
public static void setSum(int sum) {
sum = sum;
}
}
Is there a way that creates an instance of the Sum class, then each thread adds 1 to the same instance of the Sum class? I mean not using a static method or variable.
public class Test1 implements Runnable{
Sum s = null;
public Test1(Sum s) {
this.s = s;
}
public void run() {
s.sum++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Sum s = new Sum();
for (int i = 0; i < 1000; i++) {
Thread t = new Thread(new Test1(s));
t.start();
}
System.out.println(s.getSum());
}
}
class Sum {
int sum;
public Sum() {
sum = 0;
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
sum = sum;
}
}
Important notes :
1 - sleep() is static, so it acts on the current running thread, so if you meant to sleep thread t, the correct way to do it is as in the answer
2- System.out.println(s.getSum()); isn't guaranteed to run after all threads finish .... If you want to do so, use ExecutorService
3- do your synchronized add() method instead of accessing the variable directly .... here it wont matter much, but in real life example, you might encounter race condition

Threads wating and waking up

I am trying to understand threads better so i am implementing a simple task:
i have 2 classes that implement runnable. Each one is generating 2 random integers from 1 to 10. ClassA is calculating the sum and ClassB the multiplication. Both are doing this job in a loop for 15 secs.
I have another class called General that has 2 static and synchronized methods: setVal and getVal. Each thread calls General.setVal(result) after each calculation/iteration. setVal only sets the value if it is closer to a number than its previous value. getValue only gets the value.
I have a main class that start each thread. Then there is a loop for 20 secs outputting the value set by the threads. so it is just calling getValue and prints it.
I want each thread, after one iteration to wait and notify the other one to make an iteration and so on... How can i do it?
Here is my code:
public class Particle1 implements Runnable{
//private int x;
private static final int max = 10;
private static final int min = 1;
public void run(){
long t= System.currentTimeMillis();
long end = t+15000;
while(System.currentTimeMillis() < end) {
Random rand = new Random();
int a = rand.nextInt((max - min) + 1) + min;
int b = rand.nextInt((max - min) + 1) + min;
int x = a+b;
System.out.println("P1: "+a+"+"+b+"="+x);
Gather.setRes(x);
//i want it here to sleep until the other one wakes it up.
}
}
}
public class Particle2 implements Runnable{
//private int x;
private static final int max = 10;
private static final int min = 1;
public void run(){
long t= System.currentTimeMillis();
long end = t+15000;
while(System.currentTimeMillis() < end) {
Random rand = new Random();
int a = rand.nextInt((max - min) + 1) + min;
int b = rand.nextInt((max - min) + 1) + min;
int x = a+b;
System.out.println("P2: "+a+"+"+b+"="+x);
Gather.setRes(x);
//i want it here to sleep until the other one wakes it up.
}
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Particle1());
Thread thread2 = new Thread(new Particle2());
thread1.start();
thread2.start();
long t= System.currentTimeMillis();
long end = t+20000;
while(System.currentTimeMillis() < end) {
System.out.println("Minimum is: "+Gather.getRes());
Thread.sleep(1000);
}
return;
}
}
public class Gather {
public Gather() {
// TODO Auto-generated constructor stub
}
private static int res=1000000;
public static int getRes() {
return res;
}
public synchronized static void setRes(int inres) {
if(Math.abs(inres-250)<res){
res = inres;
}
}
}
Using Threads is normally an exercise for when you want all threads to run independently, not in lock-step with each other.
However, there are times when threads need to communicate amongst themselves - in which case it is common to use some form of BlockingQueue to communicate between them. Here is an example:
public class TwoThreads {
public static void main(String args[]) throws InterruptedException {
System.out.println("TwoThreads:Test");
new TwoThreads().test();
}
// The end of the list.
private static final Integer End = -1;
static class Producer implements Runnable {
final Queue<Integer> queue;
public Producer(Queue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
queue.add(i);
Thread.sleep(1);
}
// Finish the queue.
queue.add(End);
} catch (InterruptedException ex) {
// Just exit.
}
}
}
static class Consumer implements Runnable {
final Queue<Integer> queue;
public Consumer(Queue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
boolean ended = false;
while (!ended) {
Integer i = queue.poll();
if (i != null) {
ended = i == End;
System.out.println(i);
}
}
}
}
public void test() throws InterruptedException {
Queue<Integer> queue = new LinkedBlockingQueue<>();
Thread pt = new Thread(new Producer(queue));
Thread ct = new Thread(new Consumer(queue));
// Start it all going.
pt.start();
ct.start();
// Wait for it to finish.
pt.join();
ct.join();
}
}
To truly synchronise between two threads you could use the same mechanism but use a SynchronousQueue instead.

Categories