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!!
Related
I'm looking to use a thread to process something in the background. Since this code isn't used anywhere else & is not complex I'd like to use an inline function. However the function needs a copy of an attribute at the time the thread was created i.e.: I'd like it if the output from the following example 'true' instead of 'false'
public class InlineThreadTest {
boolean value;
public static void main(String[] args) {
new InlineThreadTest();
}
InlineThreadTest() {
value = true;
java.util.concurrent.Executors.newSingleThreadExecutor().execute(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
System.out.println(value);
}
});
value = false;
}
}
... I can do what I'm looking to do by creating a separate class that implements Runnable, but having this inline seems like something that might be good.
I had a look # https://stackoverflow.com/a/362443/64696 , but cannot figure out how to mold this to my use case.
Runnable implementation is a thread and thread won't return any value. The ExecutorService.execute method just runs the thread and you have no way to get the state of the thread whether it was executed or not.
If you want to check for the task (not thread) executed by ExecutorService you should use Callable and work with sumbit(). Your modified example:
public class InlineThreadTest {
boolean value;
public static void main(String[] args) {
new InlineThreadTest();
}
InlineThreadTest() {
value = true;
java.util.concurrent.Future<Boolean> f =
java.util.concurrent.Executors.newSingleThreadExecutor().submit(new Callable<Boolean>() {
public Boolean call() {
System.out.println(value);
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
value = false;
return value;
}
});
try {
System.out.println(f.get()+" or value="+value);
} catch (Exception ex) { }
}
}
You'll get 2 lines
true
false or value=false
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.
Below is the code in which in the run method, I am always trying to get unique id from the availableExistingIds and releasing it at the same moment by making a linked list order, but in certain cases I found out that, I am getting NoSuchElementException and id is zero few times which I think should not be the case anytime.
class IdPool {
private final LinkedList<Integer> availableExistingIds = new LinkedList<Integer>();
public IdPool() {
for (int i = 1; i <= 1000; i++) {
availableExistingIds.add(i);
}
}
public synchronized Integer getExistingId() {
return availableExistingIds.removeFirst();
}
public synchronized void releaseExistingId(Integer id) {
availableExistingIds.add(id);
}
}
class ThreadNewTask implements Runnable {
private IdPool idPool;
private int id;
public ThreadNewTask(IdPool idPool) {
this.idPool = idPool;
}
public void run() {
try {
id = idPool.getExistingId();
//Anything wrong here?
if(id==0) {
System.out.println("Found Zero");
}
someMethod(id);
} catch (Exception e) {
System.out.println(e);
} finally {
idPool.releaseExistingId(id);
}
}
// This method needs to be synchronized or not?
private synchronized void someMethod(Integer id) {
System.out.println("Task: " +id);
// and do other calcuations whatever you need to do in your program
}
}
Problem Statement:-
How can I avoid this zero id case here in my code? One scenario under which I can get id = 0 is when the id pool is exhausted (empty). When that happens, the line:
id = idPool.getExistingId();
will fail with a NoSuchElementException. In this case, the finally block will run:
idPool.releaseExistingId(id);
But id will still have its default value of 0 since the first line failed. So I end up "releasing" 0 and adding it back to the id pool even though it was never in the pool to start with. Then a later task could take 0 legitimately. And that's what I don't need. Can anyone suggest me how to overcome this scenario in my code? I always want id should be in the range of 1 to 1000.
why don't you modify your code so that instead of crashing when there are no available ids, it waits for one to become available?
Otherwise, every time you have too much threads working at once, the pool is going to be exhausted, and you are going to have to deal with a lot of failing threads. Also the synchronization work is taken care of for you automatically.
EDIT: here is the modified code
class ThreadNewTask implements Runnable {
private BlockingQueue<Integer> pool;
private int id;
public ThreadNewTask(BlockingQueue<Integer> pool) {
this.pool = pool;
}
public void run() {
try {
id = pool.take();
someMethod(id);
} catch (Exception e) {
System.out.println(e);
} finally {
pool.offer(id);
}
}
private void someMethod(Integer id) {
System.out.println("Task: " +id);
// and do other calcuations whatever you need to do in your program
}
}
And then you initialize the pool with something like this:
LinkedList<Integer> availableExistingIds = new LinkedList<Integer>();
for (int i = 1; i <= 1000; i++) {
availableExistingIds.add(i);
}
BlockingQueue<Integer> pool = new ArrayBlockingQueue<Integer>(1000, false, availableExistingIds);
I'm testing a Java multi-threading sample code but the thread started in the for loop of qB.start() is blocked because it's waiting for entry of qB monitor. What is the cause of this blockage?
Thank you.
import java.util.*;
class QA {
public synchronized void open() throws Exception {
Thread o = new Thread() {
public void run() {
QB qB = new QB();
qB.start();
}
};
o.start();
}
public static void main(String args[]) throws Exception {
new QA().open();
}
public class QB {
private boolean shutdown;
private Vector<Thread> tList;
private final Object waitingLock = new Object();
public QB() {
tList = new Vector<Thread>();
}
public synchronized void start() {
for(int i = 0; i < 1; i++) {
final int id = i;
Thread t = new Thread("Thread " + id) {
public void run() {
load(id);
}
};
tList.add(i, t);
t.start();
}
tMonitor();
waitUntilFinished();
}
private void tMonitor() {
Thread cmt = new Thread("T Monitor Thread") {
public void run() {
synchronized(waitingLock) {
while(tList.size() > 0) {
try {
sleep(10000);
} catch(Exception e) {
e.printStackTrace();
}
}
waitingLock.notifyAll();
}
}
};
cmt.start();
}
private void waitUntilFinished() {
synchronized(waitingLock) {
while(!isShutDown()) {
try {
waitingLock.wait();
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
private synchronized void load(int id) {
try {
System.out.println("blocked here");
// some work done here
removeFromTList(id);
} catch(Exception e) {
e.printStackTrace();
}
}
public synchronized boolean isShutDown() {
return shutdown;
}
}
}
The first problem I see is that QB#start() is synchronized on the instance of QB.
Inside the thread t that you are trying to spawn, load(id) is also synchronized on the same instance of QB. So when you call t.start() the t thread blocks until QB#start() finishes.
Presumably, at the end of the QB#start() method, QB#waitUntilFinished() is supposed to wait for all the t threads to finish, but they can't even enter the QB#load method because they're still waiting for the QB#start() method to release the lock on the QB instance.
So, circular deadlock.
Edit:
Ok, now that we see how the threads are removed from tList the bug is fully revealed.
If the index 0 thread finishes first then it will remove itself from the list. That means when the index 1 thread finishes, it will remove the 1th position from the Vector but that does not point to itself anymore. It is removing the #2 thread. Sooner or later you are going to get an exception when the remove happens because it is going to be removing an invalid index.
You need to remove items from the Vector by address and not by position:
tList.remove(this);
That will remove the current thread from the list. You should also just do an add(t) instead of an add(i t) in the start loop:
tList.add(t);
You now don't need the id position passed into your thread at all.
I don't see where you are removing the finished threads from your tList. I see a definition (not that you edited your OP) of a removeFromTList() method but I don't see it used anywhere. In tMonitor you are in a while loop here:
while(tList.size() > 0) {
try {
sleep(10000);
} catch(Exception e) {
e.printStackTrace();
}
}
// you never get to this line
waitingLock.notifyAll();
But I don't see anything that removes the thread from the list. Maybe when the threads each finish they are supposed to remove themselves?
If tMonitor thread never gets out of that loop then it never calls:
waitingLock.notifyAll();
So the main thread will hang forever in waitUntilFinished();.
synchronized(waitingLock) {
while(!isShutDown()) {
try {
waitingLock.wait();
} catch(Exception e) {
e.printStackTrace();
}
}
Also, you don't want to do a sleep in tMonitor() because you are in a synchronized block. You should be doing a:
waitingLock.wait(10000);
Nothing will ever notify it but it's bad form to hold the lock like that in a sleep.
I am currently working on modified version of Cigarette Smoker problem. Below you can find my agent class. What I need to do in order to have three threads instead of one? So there will be three outputs instead of one.
public class agent extends Thread {
private table smokingtable;
public agent(table pSmokingtable)
{
smokingtable = pSmokingtable;
}
#Override
public void run()
{
while(true)
{
try {
Thread.sleep(5000);
} catch (Exception e) {}
smokingtable.setAgentElements();
// this triggers the smoker-threads to look at the table
output("The Agent puts " + smokingtable.getAgentElements() + table.");
// pause the agent while one smoker thread is running
}
}
public synchronized void wake()
{
try
{
notify();
} catch(Exception e){}
}
public synchronized void pause()
{
try
{
this.wait();
} catch (Exception e) {}
}
private void output(String pOutput)
{
System.out.println(pOutput);
}
}
I have done something like this but surely this is wrong.
public class agent extends Thread {
private table smokingtable;
public agent(table pSmokingtable)
{
smokingtable = pSmokingtable;
}
#Override
public void run()
{
while(true)
{
try {
Thread.sleep(5000);
} catch (Exception e) {}
smokingtable.setAgent1Elements();
output("The Agent 1 puts " + smokingtable.getAgent1Elements());
smokingtable.setAgent2Elements();
output("The Agent 2 puts " + smokingtable.getAgent2Elements());
smokingtable.setAgent3Elements();
output("The Agent 3 puts " + smokingtable.getAgent3Elements());
pause();
}
}
public synchronized void wake()
{
try
{
notify();
} catch(Exception e){}
}
public synchronized void pause()
{
try
{
this.wait();
} catch (Exception e) {}
}
private void output(String pOutput)
{
System.out.println(pOutput);
}
}
In order to have 3 threads instead of 1 you need to create 3 threads and start them.
In your case, the simplest approach is this:
Thread agent1 = new agent( );
Thread agent2 = new agent( );
Thread agent3 = new agent( );
agent1.start( );
agent2.start( );
agent3.start( );
agent1.join( );
agent2.join( );
agent3.join( );
Better way of doing things would be to use ExecutorService framework, e.g. ThreadPoolExecutor.
ExecutorService pool = Executors.newFixedThreadPool( 3 );
for ( int i = 0; i < 3; ++i )
{
pool.execute( new agent( ) );
}
// This will wait for your agents to execute
pool.shutdown( );
Maybe I completely misunderstood your question, but it looks like you need to review again the basics of working with treads in java. this would be a good place to start
In the second example it looks like you are trying to run all three agents from the same thread, and i guess this is not what you intended to do.
In the first code extract you gave, add an agent id as field and to the agent's constructor, and append this Id to the output message.
now all you need to do is to create three agent instances from somewhere (probably your main method) and call their run method from there.
public static void main(String[] args) {
for(int i = 0; i < 3; i++)
new agent(i).start();
}
have a look at this simple example