Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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 - Fatal编程技术网

Java中线程的一致性

Java中线程的一致性,java,multithreading,Java,Multithreading,这里是Java新手。 只是对这个示例程序不一致的输出感到困惑。 有时,task_queue.size()为零,有时则不是。 这可能是什么原因 输出: t4:[Task9999]已执行 t1:[Task9969]已执行 等待 完成 剩余任务数:4 进程已完成,退出代码为0 import java.util.ArrayList; public class TaskExecutor implements Runnable { private ArrayList<String>

这里是Java新手。 只是对这个示例程序不一致的输出感到困惑。 有时,task_queue.size()为零,有时则不是。 这可能是什么原因

输出:

t4:[Task9999]已执行

t1:[Task9969]已执行

等待

完成

剩余任务数:4

进程已完成,退出代码为0

import java.util.ArrayList;

public class TaskExecutor implements Runnable {

    private ArrayList<String> arr;

    public TaskExecutor(ArrayList<String> arr) {
        this.arr = arr;
    }

    @Override
    public void run() {

            String task;
            while (arr.size() != 0 &&  (task = arr.remove(0))!=null) {
                System.out.println(Thread.currentThread().getName() + " : [" + task + "] has been executed");
            }
    }
}

import java.util.ArrayList;
公共类TaskExecutor实现Runnable{
私人ArrayList arr;
公共任务执行器(ArrayList arr){
this.arr=arr;
}
@凌驾
公开募捐{
字符串任务;
而(arr.size()!=0&&(task=arr.remove(0))!=null){
System.out.println(Thread.currentThread().getName()+“:[“+任务+”]已执行);
}
}
}
import java.util.ArrayList;
公共班机{
公共静态void main(字符串[]args)引发InterruptedException{
ArrayList任务_队列=新建ArrayList();
对于(int i=0;i<10000;i++){
任务队列。添加(“任务”+i);
}
线程t1=新线程(新任务执行器(任务队列));
线程t2=新线程(新任务执行器(任务队列));
线程t3=新线程(新任务执行器(任务队列));
线程t4=新线程(新任务执行器(任务队列));
线程t5=新线程(新任务执行器(任务队列));
t1.集合名(“t1”);
t2.设定名称(“t2”);
t3.设定名称(“t3”);
t4.设定名称(“t4”);
t5.设定名称(“t5”);
t1.start();
t2.start();
t3.start();
t4.开始();
t5.开始();
System.out.println();
而(t1.isAlive()|| t2.isAlive()| t3.isAlive()| t4.isAlive()| t5.isAlive()){
}
System.out.println(“等待…”);
Thread.currentThread().sleep(2000);
系统输出打印项次(“完成”);
System.out.println(“剩余任务数:+task_queue.size());
}
}

原因是ArrayList不是线程安全的

使用线程安全的集合之一,如
CopyOnWriteArrayList
。或者更好:
Collections.synchronizedList(新的ArrayList())


例如,不使用同步的集合进行同步的一种可能方式:

public class TaskExecutor implements Runnable {

    private ArrayList<String> arr;

    public TaskExecutor(ArrayList<String> arr) {
        this.arr = arr;
    }

    @Override
    public void run() {

            String task;

                while (true) 
                {
                    synchronized(arr)
                    {
                        if(arr.size()==0)
                           break;

                        task = arr.remove(0);
                        if(task==null)
                           break;
                    }

                    System.out.println(Thread.currentThread().getName() + " : [" + task + "] has been executed");

                }//end while    

    }//end run

}//end class
公共类TaskExecutor实现可运行{
私人ArrayList arr;
公共任务执行器(ArrayList arr){
this.arr=arr;
}
@凌驾
公开募捐{
字符串任务;
while(true)
{
同步(arr)
{
如果(arr.size()==0)
打破
任务=arr.remove(0);
如果(任务==null)
打破
}
System.out.println(Thread.currentThread().getName()+“:[“+任务+”]已执行);
}//结束时
}//终点
}//末级

ArrayList故意不是线程安全的。您可以使用旧的类向量(它以一定代价提供线程安全性),也可以显式地自己同步。另请参见。@michalk他是Java新手。在这个阶段,最好理解引擎盖下发生了什么,而不是使用线程安全的数据结构,这是一个很好的例子。但是,将“工作”部分(即System.out.println)放在同步块之外可能会鼓励看到您的示例的人更好地实现。@TrevorHarrison我同意,我正在考虑将其移到外部,因为它不是关键部分的一部分
public class TaskExecutor implements Runnable {

    private ArrayList<String> arr;

    public TaskExecutor(ArrayList<String> arr) {
        this.arr = arr;
    }

    @Override
    public void run() {

            String task;

                while (true) 
                {
                    synchronized(arr)
                    {
                        if(arr.size()==0)
                           break;

                        task = arr.remove(0);
                        if(task==null)
                           break;
                    }

                    System.out.println(Thread.currentThread().getName() + " : [" + task + "] has been executed");

                }//end while    

    }//end run

}//end class