Chaim_chen 2022-12-05 12:18 采纳率: 50%
浏览 231
已结题

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

  • 写回答

3条回答

  • CSDN-Ada助手 CSDN-AI 官方账号 2022-12-05 15:11
    关注
    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 12月13日
  • 修改了问题 12月6日
  • 修改了问题 12月6日
  • 赞助了问题酬金15元 12月6日
  • 展开全部

悬赏问题

  • ¥20 WPF MVVM模式 handycontrol 框架, hc:SearchBar 控件 Text="{Binding NavMenusKeyWords}" 绑定取不到值
  • ¥15 需要手写数字信号处理Dsp三个简单题 不用太复杂
  • ¥15 数字信号处理考试111
  • ¥15 allegro17.2生成bom表是空白的
  • ¥15 请问一下怎么打通CAN通讯
  • ¥20 如何在 rocky9.4 部署 CDH6.3.2?
  • ¥35 navicat将excel中的数据导入mysql出错
  • ¥15 rt-thread线程切换的问题
  • ¥15 高通uboot 打印ubi init err 22
  • ¥15 R语言中lasso回归报错