簡體   English   中英

java arraylist通過java 8中的remove方法返回相同的對象

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM