Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何确保一行代码对每个线程只运行一次?_Java_Multithreading_Threadpool_Executorservice - Fatal编程技术网

Java 如何确保一行代码对每个线程只运行一次?

Java 如何确保一行代码对每个线程只运行一次?,java,multithreading,threadpool,executorservice,Java,Multithreading,Threadpool,Executorservice,我有几个线程同时运行,每当每个线程启动时,我希望每个线程都从stringarraylist中获取一个项目,并保留该特定的唯一项目,直到它完成。实现这一点的好方法是什么?在线程中的run方法中,我考虑了字符串uniqueItem=itemList.get(k);和k++之后,但线程将一遍又一遍地运行该特定行,下次再次运行时,它将保留一个不同的唯一项。有没有办法让每个线程只获取一个项目一次,下一个线程获取可用的项目,依此类推,并保留该项目 ItemHolder thread = new Item

我有几个线程同时运行,每当每个线程启动时,我希望每个线程都从stringarraylist中获取一个项目,并保留该特定的唯一项目,直到它完成。实现这一点的好方法是什么?在线程中的run方法中,我考虑了字符串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
    }
}
ItemHolder线程=新的ItemHolder();
private ArrayList itemList=new ArrayList()//包含4个字符串(例如苹果、橘子、西瓜、梨)
int k=0;
ExecutorService executor=Executors.newFixedThreadPool(4)//例如,运行4个线程
执行器。执行(线程);
类ItemHolder扩展线程{
公开募捐{
String uniqueItem=itemList.get(k);//希望第一个线程获取第一个索引项0,并一直保持到它完成。但是其他运行相同的线程,我希望它具有索引项1,并保持该索引项,另一个线程具有任何可用的索引项,依此类推。
k++;//这将是一个问题
}
}

您希望避免两个线程同时执行get()然后同时递增k的情况。要实现这一点,必须确保每个线程都以原子方式递增k。你可以用它来做这件事

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...
    }
}
private ArrayList itemList=new ArrayList();
AtomicInteger a=新的AtomicInteger();
ExecutorService executor=Executors.newFixedThreadPool(4);

对于(int i=0;i您正在使用
ExecutorService
。这意味着您不需要传递
线程
实例,但
可运行
就足够了

话虽如此,您将创建
Runnable
实例,并以某种循环方式将它们传递给
ExecutorService
。您可以在本地字段中维护每个Runnable的状态,您可以在其中存储运行该Runnable实例的索引


如果未设置runnable的状态,则需要进行检查,然后将其设置为runnable将操作的元素。如果已设置状态,则不执行任何操作。

您应该使用
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);
        }
    }
}
公共类ItemHolderDemo{
公共静态void main(字符串[]args){
BlockingQueue=新建LinkedBlockingQueue();
队列。添加(“a”);
添加(“b”);
Runnable线程=新的ItemHolder(队列);
ExecutorService executor=Executors.newFixedThreadPool(4);//例如,运行4个线程
执行器。执行(线程);
}
静态类ItemHolder扩展线程{
阻塞队列;
公共项目持有者(阻止队列){
this.queue=队列;
}
公开募捐{
字符串uniqueItem=null;
//使用while循环以防中断
while(uniqueItem==null){
试一试{
//如果需要定时等待,请将queue.poll()与break语句一起使用
uniqueItem=queue.take();
}捕捉(中断异常e){
}
}
//得到项目
系统输出打印项次(唯一项);
}
}
}

k
类成员吗?听起来你需要
k
才是线程安全的,所以你应该使用
AtomicInteger
。参见[Jon Skeet的答案]()