Reputation: 422
I have two thread which are sharing same list, fist thread adding new object in list, and second is performing the remove on same list. after some time of start both thread i got same object, why and how?
JAVA code: SubmitJob adding ThreadRuning class in to list.
public class SubmitJob extends Thread{
public SubmitJob(List l){
list = l;
}
List<ThreadRuning> list;
private static int counter =0;
public void run(){
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ThreadRuning t = new ThreadRuning();
t.setThreadname("Thread Name "+counter);
t.setStarttime(new Date().getTime());
list.add(t);
//System.out.println("Submited"+t.getThreadname());
counter++;
}
}
}
Second class is just removing object from list.
public class JobMoniter extends Thread {
public JobMoniter(List l){
list = l;
}
List<ThreadRuning> list;
public void run() {
while (true) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (list.size()>0) {
ThreadRuning t = list.remove(0);
System.out.println(t.getState()+" name "+t.getThreadname());
if(t!=null)t.start();
//System.out.println("Startinf job"+t.getThreadname());
}
}
}
}
When i get error java.lang.IllegalThreadStateException
i was think it is related thread issue, after some study i found because of trying to start same thread twice. and getting this error so i pint the name of thread which i get from list than i know the remove method is returning same object twice once list size is increase, it is possible in java?
rest of code is below.
public class ThreadUtile {
public static void main(String[] args) {
List<ThreadRuning> list = new ArrayList<ThreadRuning>();
new SubmitJob(list).start();
new JobMoniter(list).start();
}
}
ThreadRuning
class:
public class ThreadRuning extends Thread{
private long starttime;
private String threadname;
public void run(){
for(int i=0;i<10;i++){
//System.out.println("Name of Thread "+threadname+ "Executing times"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// getter setter.
}
Note: i google but did not why?
And if i remove the t.start()
part from JobMoniter
class and store the thread name in string and compare next time i found same name multiple time, but not each time.
For any further query write in comment.
Upvotes: 0
Views: 241
Reputation: 45005
When you share an object, it needs to be thread safe to avoid unpredictable behavior that leads to bugs hard to fix. Here your share an ArrayList
that is not thread safe, you should use a thread safe collection instead. If you really need a List
, simply use the decorator Collections.synchronizedList(List)
as next:
List<ThreadRuning> list = Collections.synchronizedList(new ArrayList<ThreadRuning>());
new SubmitJob(list).start();
new JobMoniter(list).start();
However a Queue
seems to be much more appropriate, a ConcurrentLinkedQueue
(which is a Queue
implementation natively thread safe) could be a good choice here.
Upvotes: 1
Reputation: 37614
Beside the fact that you are trying to work in a concurrent environment on an ArrayList, you should really understand what references are in Java.
if (list.size()>0) {
ThreadRuning t = list.remove(0);
System.out.println(t.getState()+" name "+t.getThreadname());
if(t!=null)t.start();
//System.out.println("Startinf job"+t.getThreadname());
}
The method ArrayList.remove(int index) returns the removed object. It does not create a new instance of it. That's why you are getting IllegalThreadStateException
when you try to start the Thread again.
Upvotes: 1