Java中线程的一致性
这里是Java新手。 只是对这个示例程序不一致的输出感到困惑。 有时,task_queue.size()为零,有时则不是。 这可能是什么原因 输出: t4:[Task9999]已执行 t1:[Task9969]已执行 等待 完成 剩余任务数:4 进程已完成,退出代码为0Java中线程的一致性,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>
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