簡體   English   中英

在java中,多個線程在同一個字符串列表中工作?

[英]Multiple threads working off the same list of strings, in java?

我試圖找出讓多個線程在同一個字符串列表中工作的最佳方法。 例如,假設我有一個單詞列表,我想要多個線程來打印出這個列表中的每個單詞。

這就是我想出的。 該線程使用while循環,當迭代器具有next時,它會打印出來並從列表中刪除它。

import java.util.*;
public class ThreadsExample {

    static Iterator it;

    public static void main(String[] args) throws Exception {

        ArrayList<String> list = new ArrayList<>();

        list.add("comet");
        list.add("planet");
        list.add("moon");
        list.add("star");
        list.add("asteroid");
        list.add("rocket");
        list.add("spaceship");
        list.add("solar");
        list.add("quasar");
        list.add("blackhole");


        it = list.iterator();

        //launch three threads
        RunIt rit = new RunIt();

        rit.runit();
        rit.runit();
        rit.runit();

    }
}

class RunIt implements Runnable {

    public void run()
    {
        while (ThreadsExample.it.hasNext()) {
            //Print out and remove string from the list
            System.out.println(ThreadsExample.it.next());

            ThreadsExample.it.remove();
        }
    }

    public void runit() {
        Thread thread = new Thread(new RunIt());
        thread.start();
    }
}

這似乎工作,雖然我在運行期間Exception in thread "Thread-2" Exception in thread "Thread-0" java.lang.IllegalStateException錯誤中的Exception in thread "Thread-2" Exception in thread "Thread-0" java.lang.IllegalStateException得到一些Exception in thread "Thread-2" Exception in thread "Thread-0" java.lang.IllegalStateException

線程“Thread-0”中的線程“Thread-1”異常
java.lang.IllegalStateException at
java.util.ArrayList $ Itr.remove(ArrayList.java:864)at
RunIt.run(ThreadsExample.java:44)at
java.lang.Thread.run(Thread.java:745)java.lang.IllegalStateException
在java.util.ArrayList $ Itr.remove(ArrayList.java:864)at
RunIt.run(ThreadsExample.java:44)at
java.lang.Thread.run(Thread.java:745)

我是正確地執行此操作還是有更好的方法讓多個線程在同一個字符串池上工作?

更好的方法是使用並發隊列。 Queue接口用於在處理結構之前保存結構中的元素。

    final Queue<String> queue = new ConcurrentLinkedQueue<String>();
    queue.offer("asteroid");

    ExecutorService executorService = Executors.newFixedThreadPool(4);

    executorService.execute(new Runnable() {
        public void run() {
            System.out.println(queue.poll());
        }
    });

    executorService.shutdown();

我是正確地執行此操作還是有更好的方法讓多個線程在同一個字符串池上工作?

你沒有正確地做到這一點。 您的代碼未正確同步,因此其行為未明確定義。 有很多方法可以解決您提出的一般問題,但是您可以修改特定代碼中的問題的一種方法是更改RunIt.run()以正確同步:

    public void run()
    {
        while (true) {
            synchronized(ThreadsExample.it) {
                if (ThreadsExample.it.hasNext()) {
                    //Print out and remove string from the list
                    System.out.println(ThreadsExample.it.next());

                    ThreadsExample.it.remove();
                } else {
                    break;
                }
            }
        }
    }

請注意, hasNext()檢查,下一個元素的檢索以及該元素的刪除都在同一個同步塊中處理,以確保這些操作的相互一致性。 另一方面,該塊的范圍包含在循環中,因此同時執行循環的不同線程每個都有機會執行。

另請注意,雖然在這種情況下所有線程都在Iterator對象上同步,但這基本上只是為了方便(對我而言)。 只要他們都在同一對象上同步,沒關系這么多哪個對象即是。

嘗試使用List.synchronizedList將列表創建為同步列表

像這樣更新您的代碼:

ArrayList<String> list = Collections.synchronizedList(new ArrayList<>());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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