[英]java arraylist returning same object by remove method in java 8
我有兩個共享相同列表的線程,第一個線程在列表中添加新對象,第二個線程在同一列表上執行刪除。 在啟動了一段時間后,兩個線程我得到了相同的對象,為什么以及如何執行?
JAVA代碼:SubmitJob將ThreadRuning類添加到列表中。
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++;
}
}
}
第二類只是從列表中刪除對象。
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());
}
}
}
}
當我收到錯誤java.lang.IllegalThreadStateException
我認為這是與線程相關的問題,經過一番研究后,我發現由於嘗試兩次啟動同一線程。 並得到這個錯誤,所以我品脫我從列表中得到的線程的名稱,而不是知道一旦列表大小增加,remove方法將兩次返回相同的對象,這可能是在Java中嗎? 其余代碼如下。
public class ThreadUtile {
public static void main(String[] args) {
List<ThreadRuning> list = new ArrayList<ThreadRuning>();
new SubmitJob(list).start();
new JobMoniter(list).start();
}
}
ThreadRuning
類:
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.
}
注意:我用谷歌搜索,但為什么不呢? 如果我從JobMoniter
類中刪除t.start()
部分,並將線程名稱存儲在字符串中,並在下次進行比較,則我多次發現相同名稱,但並非每次都比較。
對於任何其他查詢,請在評論中寫。
除了您要在ArrayList上的並發環境中工作之外,您還應該真正了解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());
}
方法ArrayList.remove(int index)返回移除的對象。 它不會創建它的新實例。 這就是為什么當您嘗試再次啟動Thread時得到IllegalThreadStateException
的原因。
當您共享一個對象時,它必須是線程安全的,以避免無法預測的行為導致難以修復的錯誤。 在這里,您共享一個不是線程安全的ArrayList
,應改為使用線程安全集合。 如果確實需要List
,則只需使用裝飾器Collections.synchronizedList(List)
接下來:
List<ThreadRuning> list = Collections.synchronizedList(new ArrayList<ThreadRuning>());
new SubmitJob(list).start();
new JobMoniter(list).start();
但是, Queue
似乎更合適, ConcurrentLinkedQueue
(這是Queue
實現的本機線程安全)可能是一個不錯的選擇。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.