我有几个线程同时运行,每当每个线程开始时,我希望每个人从String Arraylist中获取一个项目,并保持该特定的唯一项目,直到它完成。实现这个的好方法是什么?在一个线程的run方法中,我虽然关于String uniqueItem = itemList.get(k);在获得它之后获得k ++,但是线程会一遍又一遍地运行该特定行,并且下次再次运行它时,它将保持不同的唯一项。有没有办法让每个线程只获得一个项目,然后下一个获得可用的内容,依此类推,并保留该项目。
ItemHolder thread = new ItemHolder();
private ArrayList<String> itemList = new ArrayList<String>(); //Contains 4 Strings (e.g. Apple, Orange, Watermelon, Pear)
int k = 0;
ExecutorService executor = Executors.newFixedThreadPool(4); //E.g. run 4 Threads
executor.execute(thread);
class ItemHolder extends Thread{
public void run(){
String uniqueItem = itemList.get(k); //Would like the first thread to grab the first index item, 0, and hold onto it until it finishes. But other thread that runs the same, I would like it to have index item, 1, and hold onto that, and the other thread to have whatever is available and so on.
k++; //This would be a problem
}
}
答案 0 :(得分:1)
您应该使用java.util.concurrent.BlockingQueue
,因为ArrayList
不是线程安全的。
示例代码:
public class ItemHolderDemo {
public static void main(String[] args) {
BlockingQueue<String> queue = new LinkedBlockingQueue<>();
queue.add("a");
queue.add("b");
Runnable thread = new ItemHolder(queue);
ExecutorService executor = Executors.newFixedThreadPool(4); //E.g. run 4 Threads
executor.execute(thread);
}
static class ItemHolder extends Thread {
BlockingQueue<String> queue;
public ItemHolder(BlockingQueue<String> queue) {
this.queue = queue;
}
public void run() {
String uniqueItem = null;
// use while loop in case there is an interruption
while (uniqueItem == null) {
try {
// use queue.poll() with break statements if you want a timed wait
uniqueItem = queue.take();
} catch (InterruptedException e) {
}
}
// got item
System.out.println(uniqueItem);
}
}
}
答案 1 :(得分:0)
您希望避免两个线程同时执行get()然后同时增加k的情况。要实现这一点,您必须确保每个线程以原子方式递增k。您可以使用AtomicInteger来做到这一点。
private ArrayList<String> itemList = new ArrayList<String>();
AtomicInteger a = new AtomicInteger();
ExecutorService executor = Executors.newFixedThreadPool(4);
for (int i=0; i<itemList.size(); i++) { // I assume itemList will not be modified
ItemHolder thread = new ItemHolder();
executor.execute(thread);
}
class ItemHolder extends Thread{
public void run(){
int k = a.getAndAdd(1);
String uniqueItem = itemList.get(k);
// Some lengthy processing might occur here...
}
}
答案 2 :(得分:0)
您正在使用ExecutorService
。这意味着您不需要传递thread
实例,但Runnable
就足够了。
话虽如此,您将创建Runnable
个实例,并在某种循环中将它们传递给ExecutorService
。您可以在本地字段中维护每个Runnable的状态,您可以在其中存储运行Runnable实例的索引。
如果未设置runnable的状态,则检查,然后将其设置为Runnable将运行的元素。如果状态已经设置,则不执行任何操作。