I'm learning how to use Java RMI in order to code distribuded applications.
I wrote a simple program just to test some things out, I just give integers to a server through a client, and the server accumulates them in a static variable. Here is the code:
The server:
public class Adder extends UnicastRemoteObject implements IAdder {
/**
*
*/
private static final long serialVersionUID = 8229278619948724254L;
private static Integer sum = 0;
static Logger logger = Logger.getLogger("global");
protected Adder() throws RemoteException {
super();
// TODO Auto-generated constructor stub
}
#Override
public void add(int i) throws RemoteException {
System.out.println("Got: " + i);
synchronized (sum) {
sum += i;
System.out.println("The new sum is: " + sum);
}
}
#Override
public int result() throws RemoteException {
System.out.println("The sum is: " + sum);
return sum;
}
public static void main(String[] args) {
System.setSecurityManager(new SecurityManager());
try {
logger.info("Building remote object");
Adder obj = new Adder();
logger.info("Binding");
Naming.rebind("SommaServer", obj);
logger.info("Ready");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Client:
public class Client extends Thread {
static Logger logger = Logger.getLogger("global");
private IAdder obj;
private int array[] = new int[3];
public static void main(String[] args) {
try {
Client c1 = new Client(1);
Client c2 = new Client(2);
c1.start();
c2.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void work(int i) throws RemoteException {
obj.add(i);
}
public void run() {
Random rn = new Random();
try {
work(array[0]);
work(array[1]);
work(array[2]);
} catch (Exception e) {
e.printStackTrace();
}
}
public Client(int i) throws Exception {
if (i == 1) {
array[0] = 1;
array[1] = 3;
array[2] = 4;
}
if (i == 2) {
array[0] = 7;
array[1] = 2;
array[2] = 5;
}
logger.info("Remote object lookup");
obj = (IAdder) Naming.lookup("rmi://localhost/SommaServer");
}
}
In the main of the client I create two client threads, and run them (there are no synchronicity checks I know, but I'm just trying things out). Each thread has an array of numbers to feed to the server.
The server receives them and then adds them all togheter.
So, since I'm dealing with threads, my first thought was that I needed to use a lock on the update of the sum, otherwise I would likely get errors because of the interleaving of the threads. Hence the synchronized block in the server.
But then, to see what would happen, I removed the block, and I was still getting the right result, all the time (the values is 22).
Just to be sure I made a "local" version of the client too, which updates a local variable:
public class Client extends Thread {
private static Integer sum = 0;
static Logger logger = Logger.getLogger("global");
private IAdder obj;
private int array[] = new int[3];
public static void main(String[] args) {
try {
Client c1 = new Client(1);
Client c2 = new Client(2);
c1.start();
c2.start();
c1.join();
c2.join();
System.out.println("Ricevuto: " + sum);
} catch (Exception e) {
e.printStackTrace();
}
}
public void work(int i) throws RemoteException {
//obj.add(i);
synchronized(sum) {
sum += i;
}
}
public void run() {
Random rn = new Random();
try {
work(array[0]);
work(array[1]);
work(array[2]);
} catch (Exception e) {
e.printStackTrace();
}
}
public Client(int i) throws Exception {
if (i == 1) {
array[0] = 1;
array[1] = 3;
array[2] = 4;
}
if (i == 2) {
array[0] = 7;
array[1] = 2;
array[2] = 5;
}
}
}
With synchronization I get the right result, without I get various numbers (8, 15, 14, 22...)
So, what is going on exactly? I doubt RMI can just be thread safe like that.
Extra question: When I bind an object in RMI, what exactly am I binding? The specific instance of the object I call Naming.rebind() on, or the class(and then when I look it up I just get a new instance?)?
Your synchronization is broken, so you can't deduce much by your experiment. Each time you do sum += i, you assign a new Integer to sum. So the threads synchronize on two different Integers.
Also, you're binding an instance of Sommatore, but you're showing the code of Adder.
But to answer your question, you're binding an instance, and RMI won't magically create copies of that instance. It won't synchronize all calls to this instance either. So you need to make sure the code is thread-safe. Just because a quick test produces a correct result despite the absence of proper synchronization doesn't mean that it will always be that way. You can cross a road with your eyes shut 10 times and never die. That doesn't mean it's safe.
Is RMI automatically "thread-safe"?
No.
Extra question: when I bind an object in RMI, what exactly am I binding? The specific instance of the object I call Naming.rebind() on, or the class(and then when I look it up I just get a new instance?)?
Actually neither. You are binding a stub, which is irretrievably associated with the remote object instance you supplied to the bind() method.
Related
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
So my teacher posted some code with examples of synchronized code and non synchronized and he is trying to teach us the differences between putting synchronized on a method and a block of code. I dont see the difference in his code by running the application but perhaps you guys can see it and explain. Ill post the code and if there is something missing with the information that im giving you guys just leave a comment and i will edit as soon as possible. So there are two classes which are related to each other. And these are the following. The commented methods are the one that im supposed to try. So the first method im supposed to run with synchronized public int incCounter() { and without. The rest of the methods im supposed to run without synchronizing public int incCounter() {. But i dont see the difference.
package f6;
public class Counter1Thread extends Thread {
private Counter1 counter;
private int times;
public Counter1Thread(Counter1 counter, String name, int times) {
this.counter = counter;
this.setName(name);
this.times = times;
}
// Testa med Counter1-incCounter a) utan synchronized b) med synchronized
// public synchronized void run() {
// int value;
// System.out.println(getName() + " startar");
// while (times-->0) {
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {}
// value = counter.incCounter();
// System.out.println(getName()+": "+value);
// }
// }
// testa med Counter1-incCounter utan synchronized
// public synchronized void run() {
// int value;
// System.out.println(getName() + " startar");
// while (times-->0) {
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {}
// synchronized(counter) {
// value = counter.incCounter();
// }
// System.out.println(getName()+": "+value);
// }
// }
// testa med Counter1-incCounter utan synchronized
// public void run() {
// int value;
// System.out.println(getName() + " startar");
// while (times-->0) {
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {}
// synchronized(counter) {
// value = counter.incCounter();
// System.out.println(getName()+": "+value);
// }
// }
// }
public static void main(String[] args) {
Counter1 counter = new Counter1();
Counter1Thread ct1 = new Counter1Thread(counter,"A",20);
Counter1Thread ct2 = new Counter1Thread(counter,"B",20);
ct1.start();
ct2.start();
}
}
package f6;
import java.util.Random;
public class Counter1 {
private int counter;
private Random rand = new Random();
public int incCounter() {
counter = counter + 1;
return counter;
}
// public synchronized int incCounter() {
// counter = counter + 1;
// return counter;
// }
}
The synchronized on the run methods don't do anything in these examples. You should ignore these. They are at best an example of randomly and incorrectly placed synchronization statements.
The key differences between the implementations are the differences between the (commented out) examples one and three: Example one has no synchronization around the increment operation, while the third example wraps increment with a synchronized statement:
value = counter.incCounter();
System.out.println(getName()+": "+value);
synchronized (counter) {
value = counter.incCounter();
System.out.println(getName()+": "+value);
}
The third example is the equivalent of the fourth example:
public synchronized int incCounter() {
counter = counter + 1;
return counter;
}
Which is the same as:
public int incCounter() {
synchronized (this) {
counter = counter + 1;
return counter;
}
}
Note that this from this fourth example is the same as counter from the third example.
What you should see is that the un-synchronized example doesn't reliably increment the counter. (You may not see the effect every time you run the test, as the result will depend on the timing of the two threads which are used by the test.)
I've been using this code: https://www.tutorialspoint.com/java/lang/runtime_addshutdownhook.htm - to save critical data upon termination. However, I get an error message:
Exception in thread "Thread-0" java.lang.NullPointerException
This occurs when I try to return an instance of an object, the process of which was terminated. To clarify, the data I am returning has been initiated, i.e. it has some default values. So, it should at least return the default values, but not the error. My only explanation would be to think it's all because of GC.
Should I use try{}catch{}finally{} to save critical data? Or is addShutdownHook supposed to work just fine with the method I am describing, so I should either provide more information on the code or try to find an error in my code?
EDIT 1:
Using this as my main:
public class Main {
private static Object objectInstance;
// a class that extends thread that is to be called when the program is exiting
static class Message extends Thread {
public void run() {
System.out.println("Object " + objectInstance.getTemporary()
+ " " + objectInstance.isExists());
System.out.println("Bye.");
}
}
public static void main(String[] args) {
try {
// register Message as shutdown hook
Runtime.getRuntime().addShutdownHook(new Message());
// print the state of the program
System.out.println("Program is starting...");
// call the object instances
for (int i = 0; i < 5; i++) {
System.out.println("Next...");
objectInstance = new Object(i);
}
// print that the program is closing
System.out.println("Program is closing...");
} catch (Exception e) {
e.printStackTrace();
}
}
}
And this as my object:
public class Object {
private boolean exists = false;
private int temporary;
public Object(int temporary) {
this.temporary = temporary;
try {
Thread.sleep(3000);
// upon completion
exists = true;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// returns to main
public boolean isExists() {
return exists;
}
// return the index
public int getTemporary() {
return temporary;
}
}
Apparently, if you terminate when the first instance of the object is in the process, it will throw the error I am talking about. Afterwards, say on the third instance of the object, it will print the information on the previous object (second in this case). It isn't saving the latest instance. Should I create an empty initialiser, and then the processing? Apparently, it does not save the instance in the main because of that.
This fixes my issue. For main:
for (int i = 0; i < 5; i++) {
System.out.println("Next...");
objectInstance = new Object(i);
System.out.println("Initialised.");
objectInstance.method();
}
For object:
public Object(int temporary) {
this.temporary = temporary;
}
public void method() {
try {
Thread.sleep(3000);
// upon completion
exists = true;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Thanks!!
I want to make an object in a new thread, that will create another thread. In that last created threads I need a reference for variable from exact object that created this thread. So far I have this code:
Main
public static void main(String[] args) {
for(int i = 0; i < 2; i++){
ClassThread ct = new ClassThread();
Thread t = new Thread(ct);
t.start();
}
}
ClassThread
public static volatile int liczba = 1;
private static int id = 0;
#Override
public void run() {
for(int i = 0; i < 2; i++){
Class1 cla = new Class1(liczba, id);
Thread t = new Thread(cla);
t.start();
id++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Class1
private volatile int var;
private int id;
public Class1(int _var, int _id) {
var = _var;
id = _id;
}
#Override
public void run() {
while(true){
System.out.println("Thread: " + id + " : " + var);
var++;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
If you need to get an int reference from one thread to another, you either have to specify your own MutableInteger class, or use AtomicInteger. The atomic integer has the positive side-effects in that operations can be made atomic. For a more exhaustive answer, see This answer.
If the question is regarding non-primitive types, you can simply pass the needed reference to the constructor as you are already attempting to do. Any changes to the internal state of that object will be reflected to all holders of a reference. Some objects are immutable (String being the perhaps most well-known, but be aware that Integer, Long, etc. works the same way.), and can therefore not be used in this way.
Do note that if you pass a reference, any assignments done to your internal reference var = "hello"; will not affect anything outside your class. You will simply exchange your private reference for another one, leaving all other references to the old object as they are. This has to do with the fact that Java is always pass-by-value.
how can I get in stop() thread names like i did in start()? Thread names are A,B,C,D. My program runs thread in order and stops them in revers order. But I have problem with printing their names. In start() I do it without any problems but in stop() I just dont know how to do it. I'm pretty new in java and this is one of my firs programs that I did that is why i dont know how to do this.
Thank you so much for your help.
Here is the code:
import java.util.*;
class Service extends Thread
{
private RobotController controller;
public String robotID;
private byte[] lock;
public Service(RobotController cntrl, String id)
{
controller = cntrl;
robotID = id;
}
public byte[] getLock() { return lock;}
public void run()
{
lock = new byte[0];
synchronized(lock)
{
byte[] data;
while ((data = controller.getData()) == null)
{
try {
lock.wait();
} catch (InterruptedException ie) {}
}
System.out.println("Thread " + robotID + " Working" );
}
}
}
class RobotController
{
private byte[] robotData;
private Vector threadList = new Vector();
private Service thread_A;
private Service thread_B;
private Service thread_C;
private Service thread_D;
public void setup(){
thread_A = new Service(this, "A");
thread_B = new Service(this, "B");
thread_C = new Service(this, "C");
thread_D = new Service(this, "D");
threadList.addElement(thread_A);
threadList.addElement(thread_B);
threadList.addElement(thread_C);
threadList.addElement(thread_D);
thread_A.start();
thread_B.start();
thread_C.start();
thread_D.start();
start();
stop();
}
public void start()
{
System.out.println("START:");
{
for (int i=0; i <threadList.size(); i++)
{
try {
Thread.sleep(500);
}catch (InterruptedException ie){
System.out.println(ie);
}
putData(new byte[10]);
Service rbot = (Service)threadList.elementAt(i);
byte[] robotLock = rbot.getLock();
synchronized(robotLock) {
robotLock.notify();
}
}
}
}
public void stop()
{
Collections.reverse(threadList);
System.out.println("STOP:");
for ( Object o : threadList) {
System.out.println("Thread "+ o +" Stop");
}
}
public synchronized byte[] getData()
{
if (robotData != null)
{
byte[] d = new byte[robotData.length];
System.arraycopy(robotData, 0, d, 0, robotData.length);
robotData = null;
return d;
}
return null;
}
public void putData(byte[] d) { robotData = d;}
public static void main(String args[])
{
RobotController controller = new RobotController();
controller.setup();
}
}
Thread has name and getter getName(), so if you have instance of thread you can always call thread.getName().
I do not know how do you access the thread name "in start" because I do not see where do you call getName(). However I think I know what's your problem in stop.
You store your threads in Vector. Then you iterate over vector's elements and print thread, so it invokes thread's toString(). You probably have to cast Object to Thread and call its getName():
System.out.println("STOP:");
for ( Object o : threadList) {
System.out.println("Thread "+ ((Thread)o).getName() +" Stop");
}
But once you are done, I'd recommend you to find a good and new enough tutorial on java.
You are using not commonly applicable coding formatting.
You are using Vector instead of List and its implementations.
You are trying to use unclear technique for thread synchronization and management.
Start learning step-by-step. And do not hesitate to ask questions. Good luck.