有 Java 编程相关的问题?

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

多线程为什么线程池中的任务不在FIFO、Java之后执行

我知道如果队列已满,新任务将由新创建的线程按照How to guarantee FIFO execution order in a ThreadPoolExecutor的优先级执行

但我有以下测试代码片段,最小核心大小=最大核心大小

public class ThreadPoolFifoTest {
    public static void main(String[] args) throws InterruptedException {
        Executor ex = Executors.newFixedThreadPool(10);
        final List<Integer> l = new LinkedList<Integer>();
        final ReentrantLock lock = new ReentrantLock(true);//fair lock
        for(int i=0;i<10000;i++){
            final int num = i ;
            ex.execute(new Runnable() {//FIFO submit 
                @Override
                public void run() {
                    //here since queue is FIFO, it is easy to consider that somebody should be take the task FIFO and let the thread to run this task
                    //so it easy to consider that this should be fifo to go to here. 
                    //But as a result , it is not.
                    lock.lock();
                    l.add(num);
                    lock.unlock();                 
                }
            });
        }

        Thread.sleep(1000);
        System.out.println(l);
        List<Integer> sortedList= new LinkedList<Integer>(l);
        Collections.sort(sortedList);
        System.out.println(sortedList);
        System.out.println(l.equals(sortedList));//not equals here

    }
}

输出:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 9, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 84, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
false

因为线程池下的队列是FIFO,所以任务应该是轮询FIFO并在线程中运行,所以因为我按照0.1.2.3.4的顺序提交任务。。。。。999,我的l看起来应该是排序的,但是从输出来看,它不是,这不是意味着执行顺序不是FIFO吗?为什么不呢

如果我需要FIFO执行任务,该怎么办


共 (1) 个答案

  1. # 1 楼答案

    问题是线程只按顺序接收消息,但独立运行(正如线程应该做的那样),如果希望在FIFO中执行,则应该

    • 使用单个线程,因为您无论如何都不能并行运行任务
    • 使用多线程,但按照创建结果的顺序(而不是执行结果的顺序)收集结果。这就是parallelStream所做的

    比如说

    List<Result> results = IntStream.range(0, 10000).parallel()
                                    .mapToObject(i -> func(i))
                                    .collect(Collector.toList());
    

    这将允许并发执行,但结果将按原始顺序显示

    顺便说一句,对LinkedList排序时,它必须将其转换为数组,排序并将其复制回链接列表。我建议使用可以就地排序的ArrayList