有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java中线程的多线程一致性

这里是Java新手。 只是对这个示例程序不一致的输出感到困惑。 有时,任务队列。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;

public class Main {

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

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

        for(int i = 0; i < 10000; i++) {
            task_queue.add("Task" + i);
        }

        Thread t1 = new Thread(new TaskExecutor(task_queue));
        Thread t2 = new Thread(new TaskExecutor(task_queue));
        Thread t3 = new Thread(new TaskExecutor(task_queue));
        Thread t4 = new Thread(new TaskExecutor(task_queue));
        Thread t5 = new Thread(new TaskExecutor(task_queue));

        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");
        t4.setName("t4");
        t5.setName("t5");

        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();

        System.out.println();

        while(t1.isAlive() || t2.isAlive() || t3.isAlive() || t4.isAlive() || t5.isAlive()) {
        }

        System.out.println("waiting...");
        Thread.currentThread().sleep(2000);
        System.out.println("finished");
        System.out.println("Number of Tasks left : " + task_queue.size());
    }

}

共 (2) 个答案

  1. # 1 楼答案

    例如,在不使用同步集合的情况下进行同步的一种可能方法是:

    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
    
  2. # 2 楼答案

    原因是ArrayList不是线程安全的

    使用线程安全的集合之一,比如CopyOnWriteArrayList。或者更好:Collections.synchronizedList(new ArrayList<String>());

    Some explanation of thread-safe