lambda表达式引用的本地变量必须是最终变量或实际上的最终变量

问题描述:最近遇到一个问题,让你用10个线程计算1-100累加的结果,并且不能使用Synchronize。

思路:用AtomicInteger + 线程池来解决。
tip:不能使用volatile关键字(只能保证可见性,不能保证同步性),用的话需要加锁不符题意

代码如下

public class Sum1To100With10Thread {
    //创建十个线程,计算1加到100的结果,然后合并返回public class Add {//使用原子类
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        AtomicInteger sum = new AtomicInteger();
        CountDownLatch countDownLatch = new CountDownLatch(10);//设置计数器初始值为10
        ExecutorService ex = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            ex.execute(() -> {
                for (int j = 1; j <= 10; j++) {
                    sum.addAndGet(i * 10 + j);
                }
                countDownLatch.countDown();//执行完sum+之后,countDownLatch数量-1
            });
        }
        countDownLatch.await();//等待计数器归零,然后再向下执行
        System.out.println(sum);
        ex.shutdown();
    }
}

遇到问题:Error:(23, 35) java: 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量
在这里插入图片描述
知识点
Lambda表达式规则

  • 只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
  • 局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
  • 不允许声明一个与局部变量同名的参数或者局部变量。

解决方法:copy ‘i’ to effectively final temp variable

修改后的代码如下

public class Sum1To100With10Thread {
    //创建十个线程,计算1加到100的结果,然后合并返回public class Add {//使用原子类
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        AtomicInteger sum = new AtomicInteger();//只能用原子类,不能用volatile。如果用volatile得加锁
        CountDownLatch countDownLatch = new CountDownLatch(10);
        ExecutorService ex = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            int finalI = i;                                // <--------
            ex.execute(() -> {
                for (int j = 1; j <= 10; j++) {
                    sum.addAndGet(finalI * 10 + j);         //<--------
                }
                countDownLatch.countDown();//执行完sum+之后,countDownLatch数量-1
            });
        }
        countDownLatch.await();//等待计数器归零,然后再向下执行
        System.out.println(sum);
        ex.shutdown();
    }
}

运行结果:5050

最后,欢迎对本题有其他解法的大佬,在评论中分享下思路 ~

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值