星宿网站建设,南山网站建设多少钱,云南app制作,全球可以做外贸的社交网站当前我们的多线程部分已经学习了几个代码案例#xff1a; 1.单例模式 2.阻塞队列 - 生产者消费者模型 3.定时器 4.线程池 而线程存在的意义就是#xff0c;使用进程来实现并发编程会“太重了”#xff0c;创建和销毁进程都会比较耗资源。
但是线程会更加高效。此时 1.单例模式 2.阻塞队列 - 生产者消费者模型 3.定时器 4.线程池 而线程存在的意义就是使用进程来实现并发编程会“太重了”创建和销毁进程都会比较耗资源。
但是线程会更加高效。此时使用多线程就可以在很多时候代替进程来实现并发编程了。
但是随着并发程度的提高随着我们对于性能要求的标准的提高咱们发现好像线程也没有那么轻量。
当我们需要频繁创建销毁线程的时候就发现好像开销还是挺大的~
想要进一步的再提高这里的效率想出了两种办法
1.搞一个“轻量级进程” 协程/纤程但还没有被加入到Java标准库中
2.使用线程池字符串常量池、数据库连接池来降低创建/销毁线程的开销。
也就是说现在有一个可以存放线程的池子事先把需要使用的线程创建好后面需要使用的时候直接从池子里去出出来。如果用完了也还给池。因为这两个动作比创建/销毁更加高效
创建/销毁线程是交由操作系统内核完成的但是从池子里获取/还给池是咱们自己用户代码就能实现的不必交给内核操作~ 相比于内核来说用户态程序执行的行为是可控的如果要想做某个工作就会非常干净利落的完成(比如从池子里取、还给池子 但是如果是通过内核此时不清楚内核身上背负着多少个任务无法确定内核都要做哪些工作整体过程是不可控的~ ExecutorService pool Executors.newFixedThreadPool(10); 工厂模式简单的来说就是用普通的方法来代替构造方法创建对象~
此处就是构造出一个10个线程的线程池然后就可以随时安排这些线程帮我们干活了~
线程池提供了一个重要的方法submit可以给线程池提交若干个任务
public class testdemo {public static void main(String[] args) {ExecutorService pool Executors.newFixedThreadPool(10);for(int i 0 ; i 1000 ; i){int n i;pool.submit(new Runnable() {Overridepublic void run() {System.out.println(hello n);}});}}
} 运行程序后发现main线程结束了但是整个线程没结束线程池中的线程都是前台线程此时会组织进程结束~
这段代码中往线程池放了1000个任务1000任务就是由这10个线程来平均分配一下然后再执行打印差不多是一个线程执行100个注意这里并非是严格的平均可能有的多一个有的少一个
每个线程都执行完一个打印的任务后再执行下一个任务由于每个任务执行时间都差不多因此 每个线程做的任务数量就差不多~
进一步的可以认为这1000个任务就在一个队列中排队这10个线程就依次来取队列中的任务取一个就执行一个执行完了再执行下一个~
问题就来了
这么简单的代码中为什么不直接打印的时候打印 i 呢而是通过 int n i 这样的操作来完成~
这其中涉及到变量捕获。 Executors提供的工厂类 还有一个包需要我们注意一下:
java.util.concurrent 这个包里放的很多类都是和并发编程多线程编程密切相关的 所以这个包也叫做juc。 corePoolSize : 核心线程数 maximumPoolSize最大线程数 ThreadPoolExecutor相当于把里面的线程分为两类
一类是核心线程理解为正式员工一类是临时工实习生这俩之和是最大线程数~
同时允许正式员工摸鱼不允许实习生摸鱼~如果实习生摸鱼太久了就会被销毁开除。
整体的策略就是正式员工保底临时工动态调节。 long keepAliveTime: 描述了临时工摸鱼的最大时间 TimeUnit unit : 时间单位sms分钟 BlockingQueueRunnable workQueue:线程池的任务队列 ThreadFactory threadFactory : 用于创建线程线程池是需要创建线程的 RejictedExecutionHandler hander : 描述了线程池的“拒绝策略” 实际开发的时候线程池的线程数设定成多少合适呢
并没有具体的数字要具体情况具体分析不能说是1.5N、2NN是cpu的核心数等等~