LockSupport导致线程阻塞

LockSupport导致线程阻塞, 运行main方法, 可重现, jdk:1.7
  • 使用CountDownLatch即可避免该问题.代码已经贴在了下方的回答中. 但目前我更需要知道的是LockSupport为什么不行
代码块:
package com.duobaoyu.dby.enterprise.service.impl;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;

@Slf4j
public class Test {
    public static void saveOrderData() {
        // 定义开启的线程数
        AtomicInteger totalThreadCount = new AtomicInteger(5);
        // 定义没有执行结束的线程集合
        List<Thread> unFinishedThread = Collections.synchronizedList(new ArrayList<>());

        List<CompletableFuture<Void>> list = new ArrayList<>();
        list.add(save(unFinishedThread, totalThreadCount));
        list.add(save2(unFinishedThread, totalThreadCount));
        list.add(save3(unFinishedThread, totalThreadCount));
        list.add(save4(unFinishedThread, totalThreadCount));
        list.add(save5(unFinishedThread, totalThreadCount));
        CompletableFuture.allOf(list.toArray(new CompletableFuture[totalThreadCount.get()])).join();
    }

    private static CompletableFuture<Void> save(List<Thread> unFinishedThread, AtomicInteger totalThreadCount) {
        return CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000L);
                Thread thread = Thread.currentThread();
                log.info("执行方法: orderSave, 线程名:{}", thread.getName());
                threadBlocking(thread, unFinishedThread, totalThreadCount);
            } catch (Exception ignored) {
            }
        });

    }

    private static CompletableFuture<Void> save2(List<Thread> unFinishedThread, AtomicInteger totalThreadCount) {
        return CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(900L);
                Thread thread = Thread.currentThread();
                log.info("执行方法: approvalInfoSave, 线程名:{}", thread.getName());
                threadBlocking(thread, unFinishedThread, totalThreadCount);
            } catch (Exception ignored) {
            }
        });
    }

    private static CompletableFuture<Void> save3(List<Thread> unFinishedThread, AtomicInteger totalThreadCount) {
        return CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(800L);
                Thread thread = Thread.currentThread();
                log.info("执行方法: orderAddressSave, 线程名:{}", thread.getName());
                threadBlocking(thread, unFinishedThread, totalThreadCount);
            } catch (Exception ignored) {
            }
        });
    }

    private static CompletableFuture<Void> save4(List<Thread> unFinishedThread, AtomicInteger totalThreadCount) {
        return CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(700L);
                Thread thread = Thread.currentThread();
                log.info("执行方法: subOrderSave, 线程名:{}", thread.getName());
                threadBlocking(thread, unFinishedThread, totalThreadCount);
            } catch (Exception ignored) {
            }
        });
    }

    private static CompletableFuture<Void> save5(List<Thread> unFinishedThread, AtomicInteger totalThreadCount) {
        return CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(600L);
                Thread thread = Thread.currentThread();
                log.info("执行方法: orderGoodsSave, 线程名:{}", thread.getName());
                threadBlocking(thread, unFinishedThread, totalThreadCount);
            } catch (Exception ignored) {
            }
        });
    }

    private static void threadBlocking(Thread thread, List<Thread> unFinishedThread, AtomicInteger totalThreadCount) {
        // 添加到没有执行结束的线程集合
        unFinishedThread.add(thread);
        // 每个线程都在悬停前开启唤醒检查
        notifyAllThread(unFinishedThread, totalThreadCount);

        log.info("线程: {}, 开始悬停", thread.getName());
        LockSupport.park();
        log.info("线程: {}, 执行完毕", thread.getName());
    }

    private static void notifyAllThread(List<Thread> unFinishedThread, AtomicInteger totalThreadCount) {
        if (unFinishedThread.size() == totalThreadCount.get()) {
            for (Thread thread : unFinishedThread) {
                LockSupport.unpark(thread);
                log.info("线程: [{}]被唤醒", thread.getName());
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println("开始任务!" + i);
            saveOrderData();
            System.out.println("结束任务!" + i);
        }
    }
}

img

从jdk的文档来看, 是不会造成阻塞的. 目前也没有发现固定的规律, 想知道造成这种问题的原因, 以及如何解决这个问题了

main方法给了循环100次, 是因为这个线程阻塞是会出现, 但是不确定是在那一次循坏中出现.

JDK文档来看: 可以先park也可以先unpark


我使用CountDownLatch即可避免该问题. 但我需要知道的是LockSupport为什么不行

package com.duobaoyu.dby.enterprise.config;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;

@Slf4j
public class Test {
    public static void saveOrderData() {
        // 定义开启的线程数
        CountDownLatch latch = new CountDownLatch(5);

        List<CompletableFuture<Void>> list = new ArrayList<>();
        list.add(save(latch));
        list.add(save2(latch));
        list.add(save3(latch));
        list.add(save4(latch));
        list.add(save5(latch));
        // 调用Future的阻塞接口, 等待全部future实例异步执行结束
        CompletableFuture.allOf(list.toArray(new CompletableFuture[5])).join();
    }

    private static CompletableFuture<Void> save(CountDownLatch latch) {
        return CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000L);
                Thread thread = Thread.currentThread();
                log.info("执行方法: orderSave, 线程名:{}", thread.getName());
                threadBlocking(thread, latch);
            } catch (Exception ignored) {
            }
        });

    }

    private static CompletableFuture<Void> save2(CountDownLatch latch) {
        return CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(900L);
                Thread thread = Thread.currentThread();
                log.info("执行方法: approvalInfoSave, 线程名:{}", thread.getName());
                threadBlocking(thread, latch);
            } catch (Exception ignored) {
            }
        });
    }

    private static CompletableFuture<Void> save3(CountDownLatch latch) {
        return CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(800L);
                Thread thread = Thread.currentThread();
                log.info("执行方法: orderAddressSave, 线程名:{}", thread.getName());
                threadBlocking(thread, latch);
            } catch (Exception ignored) {
            }
        });
    }

    private static CompletableFuture<Void> save4(CountDownLatch latch) {
        return CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(700L);
                Thread thread = Thread.currentThread();
                log.info("执行方法: subOrderSave, 线程名:{}", thread.getName());
                threadBlocking(thread, latch);
            } catch (Exception ignored) {
            }
        });
    }

    private static CompletableFuture<Void> save5(CountDownLatch latch) {
        return CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(600L);
                Thread thread = Thread.currentThread();
                log.info("执行方法: orderGoodsSave, 线程名:{}", thread.getName());
                threadBlocking(thread, latch);
            } catch (Exception ignored) {
            }
        });
    }

    private static void threadBlocking(Thread thread, CountDownLatch latch) {
        log.info("线程: {}, 开始悬停", thread.getName());
        try {
            latch.countDown();
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("线程: {}, 执行完毕", thread.getName());
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println("开始任务!" + i);
            saveOrderData();
            System.out.println("结束任务!" + i);
        }
    }
}

LockSupport 阻塞和中断
https://blog.csdn.net/m0_45406092/article/details/113774715