多线程处理list数据,并获取线程进度是否完成

本文介绍了一种使用Java实现的多线程处理大型列表的方法。通过将列表分割为多个子列表,并为每个子列表分配一个独立线程进行处理,以此提高处理效率。文章详细展示了如何利用`CountDownLatch`确保所有线程完成任务后再继续执行主线程。
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class ThreadTest {


    /**
     * 多线程处理list
     * 
     * @param data
     *            数据LinkedList,线程安全
     * @param threadNum
     *            线程数
     * @throws InterruptedException
     */
    public synchronized void handleList(LinkedList<String> data, int threadNum) throws InterruptedException {
        int length = data.size();
        int tl = length % threadNum == 0 ? length / threadNum : (length / threadNum + 1);
        int countDownLathNum= 0;//计算线程数量
        for (int i = 0; i < threadNum; i++) {
            if ((i * tl) <= length) {
            	countDownLathNum =i+1;
            }
        }
        
        CountDownLatch latch = new CountDownLatch(countDownLathNum);// 多少协作
        System.out.println("线程数有》"+countDownLathNum);
        long a = System.currentTimeMillis();
        for (int i = 0; i < threadNum; i++) {
            int end = (i + 1) * tl;
            if ((i * tl) <= length) {
                // 继承thread启动线程
               //  HandleThread thread = new HandleThread("线程[" + (i + 1) +"] ",data, i * tl, end > length ? length : end, latch);
                // thread.start();

                // 实现Runnable启动线程
              RunnableThread thread = new RunnableThread("线程[" + (i + 1) + "] ", data, i * tl, end > length ? length : end, latch);
                Thread runable = new Thread(thread);
                runable.start();
            }
        }
        latch.await();// 等待所有工人完成工作
        System.out.println("结束*****************************");
        long b = System.currentTimeMillis();
        System.out.println("时间:" + (b - a) + "毫秒***********************");
    }

    // 继承Thread
    class HandleThread extends Thread {
        private String threadName;
        private List<String> data;
        private int start;
        private int end;
        private CountDownLatch latch;

        public HandleThread(String threadName, List<String> data, int start, int end, CountDownLatch latch) {
            this.threadName = threadName;
            this.data = data;
            this.start = start;
            this.end = end;
            this.latch = latch;
        }

        public void run() {
            // TODO 这里处理数据
            List<String> l = data.subList(start, end);
           System.out.println(threadName + "--" + data.size() + "--" + start + "--" + end + "--");
            for (int i = 0; i < l.size(); i++) {
                // 单个线程中的数据
                System.out.println(l.get(i));
            }
            latch.countDown();// 工人完成工作,计数器减一
        }
    }

    // 实现Runnable
    class RunnableThread implements Runnable {
        private String threadName;
        private List<String> data;
        private int start;
        private int end;
        private CountDownLatch latch;

        public RunnableThread(String threadName, List<String> data, int start, int end, CountDownLatch latch) {
            this.threadName = threadName;
            this.data = data;
            this.start = start;
            this.end = end;
            this.latch = latch;
        }

        public void run() {
            // TODO 这里处理数据
            List<String> l = data.subList(start, end);
            System.out.println(threadName + "--" + data.size() + "--" + start + "--" + end + "--");
            for (int i = 0; i < l.size(); i++) {
                // 单个线程中的数据
                System.out.println(l.get(i));
            }
            latch.countDown();// 工人完成工作,计数器减一
            System.out.println("latch>"+latch.getCount());
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadTest test = new ThreadTest();

        // 准备数据
        LinkedList<String> data = new LinkedList<String>();
        for (int i = 0; i < 12421; i++) {
            data.add("item" + "  " + i);
        }
        test.handleList(data, 1144);

    }
}

### 多线程技术实现大批量数据导入导出的最佳实践 #### 数据导入最佳实践 为了高效处理大批量数据的导入,可以采用多线程技术来行化操作。以下是具体方法: 1. **文件解析阶段** 使用专门的工具类(如Apache POI或EasyExcel)读取Excel文件的内容,将其转换为内存中的对象列表。此过程可以通过单线程完成,因为文件IO通常是瓶颈所在[^1]。 2. **任务拆分与分配** 将解析后的数据按照一定规则划分为若干子集,每部分由独立的工作线程负责处理。这种划分方式可以根据记录数量或者业务逻辑决定。例如,如果总共有N条记录,则可将它们均匀分布到M个工作线程中[^1]。 3. **处理** 创建一个`ExecutorService`实例用于管理线程池大小以及提交任务给各个工作线程执行。每个线程仅需专注于自己的那部分数据集合即可。 ```java ExecutorService executor = Executors.newFixedThreadPool(threadCount); List<Future<?>> futures = new ArrayList<>(); for (List<Data> subData : dataChunks) { Future<?> future = executor.submit(new WorkerThread(subData)); futures.add(future); } ``` 4. **结果收集与异常处理** 当所有线程完成了各自的任务之后,主线程应该等待这些异步调用结束通过某种机制汇总最终的结果。同时也要注意捕获可能出现的各种运行期错误以便及时反馈给用户。 5. **通知机制** 如果涉及到长时间的操作完成后需要告知相关人员的话,还可以借助邮件服务发送提醒消息[^3]。 #### 数据导出最佳实践 对于大数据量的导出需求来说,除了利用多核CPU的优势外还需要考虑其他方面因素以优化性能表现: 1. **分页查询数据库** 避免一次性加载过多的数据进入内存当中造成OOM风险,而是采取逐步获取的方式减少资源占用情况下的压力测试[^2]. 2. **流式写入目标文档** 不要等到所有的记录都被检索出来后再开始构建输出文件;相反,在每次取得一批新纪录的同时就立即将其追加至正在形成的电子表格里去[^2]. ```java EasyExcel.write(fileName).head(heads).sheet(sheetName).doWrite(dataList.stream().collect(Collectors.toList())); ``` 3. **控制线程数合理范围** 虽然增加更多的处理器确实有助于加快整体进度,但如果设置得过高反而会带来额外开销甚至降低吞吐率因此建议依据实际情况调整合适的规模参数值[^2]. 综上所述,无论是进行大规模的信息录入还是提取活动都可以充分利用现代计算机体系结构所提供的强大计算能力从而达到事半功倍的效果!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学海无涯苦做java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值