通过线程池方式改造Stream.parallel()并行流

发布时间:2025-05-19 00:06:56 作者:益华网络 来源:undefined 浏览量(1) 点赞(1)
摘要:来源:哪吒编程 上一篇简单聊一聊公平锁和非公平锁,parallel并行流,提到了一个IntStream.rangeClosed并行流问题,很多小伙伴,对这个比较陌生,想用线程池的方式改造一下。 一、IntStream.rangeClosed并行流@Datapubli

来源:哪吒编程

上一篇简单聊一聊公平锁和非公平锁,parallel并行流,提到了一个IntStream.rangeClosed并行流问题,很多小伙伴,对这个比较陌生,想用线程池的方式改造一下。

一、IntStream.rangeClosed并行流

@Datapublic class LockTest1 

{

    public static void main(String[] args) 

{

        IntStream.rangeClosed(1100000).parallel().forEach(i -> new

 LockTest1().increase());

        System.out.println(time);

    }

    private static int time = 0

;

    private static Object lock = new

 Object();

    public void increase() 

{

        synchronized

 (lock) {

            time++;

        }

    }

}

二、线程池方式改造

不会那些新特性,还是原始的香啊,写起代码,得心应手。

1、创建线程池

这时候,有些小伙伴,又陷入了选择恐惧症。用哪个线程池比较好呢?

简单回顾一下:

单线程池newSingleThreadExecutor(),只有一个核心线程的线程池,保证任务按FIFO顺序一个个执行;固定线程数线程池newFixedThreadPool(10),固定数量的可复用的线程数,来执行任务。当线程数达到最大核心线程数,则加入队列等待有空闲线程时再执行;可缓存线程池newCachedThreadPool(),创建的都是非核心线程,而且最大线程数为Interge的最大值,空闲线程存活时间是1分钟。如果有大量耗时的任务,则不适该创建方式,它只适用于生命周期短的任务;固定线程数newScheduledThreadPool(10),支持定时和周期性任务newScheduledThreadPool(10),顾名思义,在固定线程数的前提下,添加了定时任务。

最常用的还是固定线程数线程池newFixedThreadPool(10)。

@Datapublic class LockTest2 

{

    public static void main(String[] args) 

{

        ExecutorService executorService = Executors.newFixedThreadPool(200

);

        for (int i = 0; i < 100000

; i++) {

            Thread0926 thread = new

 Thread0926();

            executorService.execute(thread);

        }

        System.out.println(time);

    }

    private static int time = 0

;

    private static Object lock = new

 Object();

    public void increase() 

{

        synchronized

 (lock) {

            time++;

        }

    }

}

2、线程类

public class Thread0926 implements Runnable

{

    @Override    public void run() 

{

        LockTest2 lockTest = new

 LockTest2();

        lockTest.increase();

    }

}

3、信心满满,走起来

我草,这不对啊,不应该是100000嘛?又把老子整不会了~

三、再次解决并发时i++原子性问题

上一篇测试过,使用synchronized代码块是可以解决i++线程安全问题的,这次怎么不好使了?

上面的代码中,synchronized (lock)锁住了time++,lock是静态变量,所以属于类级别的锁。但是新建的线程是一个新的类,超出了锁的范围,所以失效。

那么,在当前类中,开启线程,是不是就可以了呢?试一下

public class LockTest4 

{

    private static int time = 0

;

    private static Object lock = new

 Object();

    public static void main(String[] args) throws InterruptedException 

{

        for (int i = 0; i < 200

; i++) {

            Thread thread = new

 Thread(() -> {

                for (int j = 0; j < 500

; j++) {

                    synchronized

 (lock) {

                        time++;

                    }

                }

            });

            thread.start();

        }

        Thread.sleep(3000

);

        System.out.println(time);

    }

}

当然,在synchronized代码块中,使用synchronized (LockTest4.class)也是可以的,效果是一样的。

四、并行流与多线程

并行流的本质的是并行,多线程的本质是并发。

并行指当多核CPU中的一个CPU执行一个线程时,其它CPU能够同时执行另一个线程,两个线程之间不会抢占CPU资源,可以同时运行。

并发指在一段时间内CPU处理多个线程,这些线程会抢占CPU资源,CPU资源根据时间片周期在多个线程之间来回切换,多个线程在一段时间内同时运行,而在同一时刻不是同时运行的。

1、并行和并发的区别?

并行指多个线程在一段时间的每个时刻都同时运行,并发指多个线程在一段时间内同时运行(不是同一时刻,一段时间内交叉执行)并行的多个线程不会抢占系统资源,并发的多个线程会抢占系统资源;并行是多CPU的产物,单核CPU中只有并发,没有并行;

2、并行和并发的使用场景

(1)IO密集场景

场景应用程序开发,提供http接口、数据库查询、微服务调用都是IO请求,IO请求时几乎不消耗cpu,这是为了提供cup使用率,建议使用多线程并发,线程数可以远大于cpu核数。

(2)cup密集场景

对应大量的加减乘除运算、md5、hash等运算操作,需要持续使用cpu,需要让多核cpu并行运算,适合使用forkjoin并行计算

技术场景多线程不足,使用多线程技术,也能提高性能,但是线程设置过大会浪费cpu线程切换的时间,如果线程任务分配不均匀,会导致有的cpu忙碌有的cpu空闲。

二维码

扫一扫,关注我们

声明:本文由【益华网络】编辑上传发布,转载此文章须经作者同意,并请附上出处【益华网络】及本页链接。如内容、图片有任何版权问题,请联系我们进行处理。

感兴趣吗?

欢迎联系我们,我们愿意为您解答任何有关网站疑难问题!

您身边的【网站建设专家】

搜索千万次不如咨询1次

主营项目:网站建设,手机网站,响应式网站,SEO优化,小程序开发,公众号系统,软件开发等

立即咨询 15368564009
在线客服
嘿,我来帮您!