java工厂模式,我的世界生存模式该怎么玩?
我的世界里面流传一句很广的话:

要致富,先撸树。
1.无论你在什么地方出生,一定要谨记一点,木头要多弄,且第一件事就是敲木头。等你有了足够的木头,就出发找牛羊,牛羊可以带来生存必需的床和肉。
2.庇护所。如果你已经有了基本活下去的物质保障就去找一个临近河或者海的森林,建造一个自己的小家。临水可以保证以后的种地需求,靠近森林可以保证物资需求,如果你是一个探险玩家,可以忽略这一点。
3.杀怪。等到你已经迈入了小康,就多多的前去杀怪,获得经验值和一些特殊的东西,比如骨头,可以用来驯服狼和种田,号称金坷垃可不是吹的。我的世界这个游戏是个沙盒类游戏,不存在固定的玩法,我只是告诉了你最基本的生存思路,并不是说你就生存模式必需这样玩,你可以有很多种选择,如果你执着于某种玩法,那么你就没有正确的领略到这个游戏的精髓所在。我的世界最大的玩法特点就是没有玩法,哪一种玩家都可以在其中找到自己想要的那一方面。爱打怪就打怪,爱挖矿就挖矿,爱建造就建造,随心所欲,不要局限住自己。
图片来自网络,侵权请联系删除。
最后请大家点个赞吧,嘿嘿。
有哪些的实用网站推荐?
极其强烈推荐这6个超实用的神仙网站
1、医学微视
https://www.mvyxws.com/
医学微视是响应落实党的十八届五中全会提出的“健康中国”国家战略,配合卫健委宣传司“健康中国行——全民健康素养促进活动”精神,为了提高公民医学素养水平,以让公众“多了解一点专业医学知识,生命和健康就多一分保障”为主旨,在中华医学会科学普及分会指导下,由中国医学科学院健康科普研究中心监制,结合互联网等现代科技方便、快捷、普众的特征,而实施的一项权威医学科普项目。
2、SubHD字幕平台
https://subhd.tv/
SubHD 网站是一个致力于分享国外电影、动漫、电视剧字幕翻译和分享的站点,帮助国内用户欣赏国外的媒体视频资源无障碍,同时还可以通过看视频来学习不同的语言,提高听力和翻译能力。
3、Topbook | 高效生活视频书
https://topbook.cc/
Topbook是一个有关「高效率」的百宝箱网站。关于生活、学习、工作,都有相关的app、网站推荐。Topbook的宗旨:推荐最纯粹的工具,让你摆脱无用讯息的控制。网站一共有4个板块,分别是:高效生活研究所、文章、计划、市集。
4、中国大学MOOC(慕课)
https://www.icourse163.org/
《中国大学MOOC》慕课是汇集了高等教育资源的学习网站,有效解决了除了小初高学生之外的大学生群体学习问题,海量免费优质课程应有尽有,四六级考试、考研、雅思精准对接,视频、直播、考试、讨论,高效学习不在话下。
5、美食杰
https://www.meishij.net/
美食菜谱网站,收天下美食菜谱,提供丰富的菜谱家常菜做法大全,全国各地菜谱大全,精美的美食图片,生动的美食视频让你最快的学会各类家常菜谱。
6、考试酷
https://www.examcoo.com/index
这个网站真的很酷,里面有各种考试题,都是非常实用,借鉴性非常强,无论是学历考试、成人考试、公务员、职称考试等都有考题可以让你参考,支持在线模拟考试。
以上是我的回答,希望可以帮助到你!
IT网络运维:扎根IT行业十几年的资深高级网络工程师, 分享IT网络运维技术知识资源, 用冷静、专业的视角带给你不一样的认知。
有什么靠谱的副业可以做吗?
对于有特长的人来说,即便是做副业,也有着一般人所没有的优势。
好在对于普通人,也不是没有机会,只要你肯努力去学,努力去做。
所谓副业,无非是在主业下班以后,利用空余时间去赚取报酬的行当。既然是为了赚取报酬,我们用以交换的就是我们的时间、我们的体力、我们的知识、我们的技能!老爷爷在利用手工进行副业创收我这里主要还是说说我所了解的,大多数普通人都可以从事的副业。
一、外卖、快递、代驾等。
夜色里的外卖小哥这一类的副业,我统统将其归为一类,那便是用我们自己的时间与体力去换取报酬。
之所以将这一类的副业放在第一个来讲,这是因为,这一类的副业是见效最快的。
按时计费或是按件计费,到了一个时间周期,薪酬便进行计算,对于有着迫在眉睫的经济压力的朋友,这一类的副业,在短期内可以说是首选。
同样,这一类的副业都有一个共性的问题。
发现问题,解决问题那就是:这一类的副业缺乏足够的收入上涨空间,存在收入天花板,多做多得,没有可成长性。
正因为如此,这一类的副业只能当作副业来做,难以将其培养成为高收入的主业。
二、运营自媒体,打造个人IP。
个人IP是核心资产第二个来聊聊自媒体运营,主要是因为自媒体的意识太深入人心,太热门了。
只要是涉足过这个领域的人就知道,如今的自媒体已经渡过了野蛮生长的时期了。随着用户数量趋于饱和,创作者数量却与日俱增,自媒体红利已经不在,不论是大V、团队,收益都出现了不同程度的下降。
去年以来,头条对创作者权益进行了数次调整,更加传达了一个明确的信号:扶持专业性、有内涵、有深度的自媒体从业人员。
正应了那句话:强者更强、弱者恒弱。
那么,如今不适合开始运用自媒体了吗?答案是否定的!
互联网经济进入下半段,个人想要从中获利,最重要的一个筹码就是“个人IP”。
在可预见的未来,个人IP将是每个人最重要的财富与资源,而打造个人IP,就离不开自媒体的运用,粉丝的获取更不是一蹴而就的,什么时候开始都不算晚。
自媒体运用不能盲目,为了走得更远,还是需要选择适合自己,或是在家有所储备的领域,我举几个例子以供参考。
1、短视频拍摄与剪辑。
这里以笔者涉足过的抖音与西瓜视频为例。
抖音发视频,是不能直接产生收益的,需要具有一定粉丝后,进行接游戏广告,或是直播带货,才能实现足量的变现,这种获得收益的方式并不适合所有人。
西瓜视频发布横板视频时勾选投放广告,在用户浏览时便可以获得一定量的创作收益。(通常以XX元/千阅读)进行计算。
当然,类似快手、小红书、B站之类也有着类似的设定,不同的网站视频受众也有所区别,需要在了解后对自己的作品进行有针对性地调整。
2、写作撰稿。
头条号,你还没有吗?运用写作进行副业创业算是我比较推荐的方式之一,入门门槛低,收入曲线上限很高,并且可以产生睡后收入,这一点十分吸引人。
当然,缺点也很明显:需要耐得住寂寞,持续输出,前期难以获得盈利,所以必须在有主业支持的前提下从事这项副业是比较稳妥的。
常见的写作撰稿方式有:
曾经的网文证道所在自媒体发表图文:知乎、头条号、百家号、企鹅号、小红书等;
网络小说创作:起点、番茄、咪咕、飞卢等;
传统文学投稿:樊登读书等。
公众号:单独拉出来是因为公众号与其他平台不同,粉丝逻辑不同,需要其他在其他平台进行引流,但是如果拥有足够的粉丝群体后,商业价值也是很高的。
3、知识干货付费。
这一类的副业有一定的门槛,比较常见的有财经类、医学类、信息类、职场类等。
知识付费类的有一个前提,往往需要从业者在主业领域中已经取得了一定的成就,或是能够掌握到一般人难以掌握的技术、信息,从而形成信息差,进而产生价值。
如果符合相关条件,这一类别其实可以与上面两种类别同时进行,更加有利于个人IP的打造。
写在文末:如果你耐心地从开头阅读到这里,你可能会发现一个关键字,“打造个人IP”。不论是抖音变现,还是头条的创作收益,网文的签约稿费,这些副业收益的背后逻辑还是在于个人IP的打造。
当然有人会说,还可以开网店,倒卖二手物品等等,但这些并不适合所有人,所以我在这里就没有介绍。
互联网创业的下半段,每一位大V的“个人IP”就是其最大的商业财富,而打造一个具有商业价值的个人IP,就需要通过持续的产出优质作品来不断获取足额的粉丝。
而只要找准方向,努力去做,未必成不了粉丝千万+的头部自媒体,成为人生赢家。
就像电影《幸运的钥匙》里表现的那样:努力的人到了哪里都会努力生活,不努力的人放在何种境地还是不会努力。
看完文章,欢迎关注、点赞与留言!
JAVA架构之线程池是怎样工作的?
提示
请带着这些问题继续后文,会很大程度上帮助你更好的理解相关知识点。@pdai为什么要有线程池?Java是实现和管理线程池有哪些方式? 请简单举例如何使用。为什么很多公司不允许使用Executors去创建线程池? 那么推荐怎么使用呢?ThreadPoolExecutor有哪些核心的配置参数? 请简要说明ThreadPoolExecutor可以创建哪是哪三种线程池呢?当队列满了并且worker的数量达到maxSize的时候,会怎么样?说说ThreadPoolExecutor有哪些RejectedExecutionHandler策略? 默认是什么策略?简要说下线程池的任务执行机制? execute –> addWorker –>runworker (getTask)线程池中任务是如何提交的?线程池中任务是如何关闭的?在配置线程池的时候需要考虑哪些配置因素?如何监控线程池的状态?为什么要有线程池线程池能够对线程进行统一分配,调优和监控:降低资源消耗(线程无限制地创建,然后使用完毕后销毁)提高响应速度(无须创建线程)提高线程的可管理性ThreadPoolExecutor例子Java是如何实现和管理线程池的?从JDK 5开始,把工作单元与执行机制分离开来,工作单元包括Runnable和Callable,而执行机制由Executor框架提供。WorkerThreadSimpleThreadPool
程序中我们创建了固定大小为五个工作线程的线程池。然后分配给线程池十个工作,因为线程池大小为五,它将启动五个工作线程先处理五个工作,其他的工作则处于等待状态,一旦有工作完成,空闲下来工作线程就会捡取等待队列里的其他工作进行执行。这里是以上程序的输出。输出表明线程池中至始至终只有五个名为 "pool-1-thread-1" 到 "pool-1-thread-5" 的五个线程,这五个线程不随着工作的完成而消亡,会一直存在,并负责执行分配给线程池的任务,直到线程池消亡。Executors 类提供了使用了 ThreadPoolExecutor 的简单的 ExecutorService 实现,但是 ThreadPoolExecutor 提供的功能远不止于此。我们可以在创建 ThreadPoolExecutor 实例时指定活动线程的数量,我们也可以限制线程池的大小并且创建我们自己的 RejectedExecutionHandler 实现来处理不能适应工作队列的工作。这里是我们自定义的 RejectedExecutionHandler 接口的实现。RejectedExecutionHandlerImpl.javaThreadPoolExecutor 提供了一些方法,我们可以使用这些方法来查询 executor 的当前状态,线程池大小,活动线程数量以及任务数量。因此我是用来一个监控线程在特定的时间间隔内打印 executor 信息。MyMonitorThread.java这里是使用 ThreadPoolExecutor 的线程池实现例子。WorkerPool.java注意在初始化 ThreadPoolExecutor 时,我们保持初始池大小为 2,最大池大小为 4 而工作队列大小为 2。因此如果已经有四个正在执行的任务而此时分配来更多任务的话,工作队列将仅仅保留他们(新任务)中的两个,其他的将会被RejectedExecutionHandlerImpl 处理。上面程序的输出可以证实以上观点。注意 executor 的活动任务、完成任务以及所有完成任务,这些数量上的变化。我们可以调用 shutdown() 方法来结束所有提交的任务并终止线程池。ThreadPoolExecutor使用详解其实java线程池的实现原理很简单,说白了就是一个线程集合workerSet和一个阻塞队列workQueue。当用户向线程池提交一个任务(也就是线程)时,线程池会先将任务放入workQueue中。workerSet中的线程会不断的从workQueue中获取线程然后执行。当workQueue中没有任务的时候,worker就会阻塞,直到队列中有任务了就取出来继续执行。Execute原理当一个任务提交至线程池之后:线程池首先当前运行的线程数量是否少于corePoolSize。如果是,则创建一个新的工作线程来执行任务。如果都在执行任务,则进入2.判断BlockingQueue是否已经满了,倘若还没有满,则将线程放入BlockingQueue。否则进入3.如果创建一个新的工作线程将使当前运行的线程数量超过maximumPoolSize,则交给RejectedExecutionHandler来处理任务。当ThreadPoolExecutor创建新线程时,通过CAS来更新线程池的状态ctl.参数corePoolSize 线程池中的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePoolSize, 即使有其他空闲线程能够执行新来的任务, 也会继续创建线程;如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行;如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程。workQueue 用来保存等待被执行的任务的阻塞队列. 在JDK中提供了如下阻塞队列: 具体可以参考JUC 集合: BlockQueue详解ArrayBlockingQueue: 基于数组结构的有界阻塞队列,按FIFO排序任务;LinkedBlockingQueue: 基于链表结构的阻塞队列,按FIFO排序任务,吞吐量通常要高于ArrayBlockingQueue;SynchronousQueue: 一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue;PriorityBlockingQueue: 具有优先级的无界阻塞队列;LinkedBlockingQueue比ArrayBlockingQueue在插入删除节点性能方面更优,但是二者在put(), take()任务的时均需要加锁,SynchronousQueue使用无锁算法,根据节点的状态判断执行,而不需要用到锁,其核心是Transfer.transfer().maximumPoolSize 线程池中允许的最大线程数。如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,前提是当前线程数小于maximumPoolSize;当阻塞队列是无界队列, 则maximumPoolSize则不起作用, 因为无法提交至核心线程池的线程会一直持续地放入workQueue.keepAliveTime 线程空闲时的存活时间,即当线程没有任务执行时,该线程继续存活的时间;默认情况下,该参数只在线程数大于corePoolSize时才有用, 超过这个时间的空闲线程将被终止;unit keepAliveTime的单位threadFactory 创建线程的工厂,通过自定义的线程工厂可以给每个新建的线程设置一个具有识别度的线程名。默认为DefaultThreadFactoryhandler 线程池的饱和策略,当阻塞队列满了,且没有空闲的工作线程,如果继续提交任务,必须采取一种策略处理该任务,线程池提供了4种策略:AbortPolicy: 直接抛出异常,默认策略;CallerRunsPolicy: 用调用者所在的线程来执行任务;DiscardOldestPolicy: 丢弃阻塞队列中靠最前的任务,并执行当前任务;DiscardPolicy: 直接丢弃任务;当然也可以根据应用场景实现RejectedExecutionHandler接口,自定义饱和策略,如记录日志或持久化存储不能处理的任务。三种类型newFixedThreadPool线程池的线程数量达corePoolSize后,即使线程池没有可执行任务时,也不会释放线程。FixedThreadPool的工作队列为无界队列LinkedBlockingQueue(队列容量为Integer.MAX_VALUE), 这会导致以下问题:线程池里的线程数量不超过corePoolSize,这导致了maximumPoolSize和keepAliveTime将会是个无用参数由于使用了无界队列, 所以FixedThreadPool永远不会拒绝, 即饱和策略失效newSingleThreadExecutor初始化的线程池中只有一个线程,如果该线程异常结束,会重新创建一个新的线程继续执行任务,唯一的线程可以保证所提交任务的顺序执行.由于使用了无界队列, 所以SingleThreadPool永远不会拒绝, 即饱和策略失效newCachedThreadPool线程池的线程数可达到Integer.MAX_VALUE,即2147483647,内部使用SynchronousQueue作为阻塞队列; 和newFixedThreadPool创建的线程池不同,newCachedThreadPool在没有任务执行时,当线程的空闲时间超过keepAliveTime,会自动释放线程资源,当提交新任务时,如果没有空闲线程,则创建新线程执行任务,会导致一定的系统开销; 执行过程与前两种稍微不同:主线程调用SynchronousQueue的offer()方法放入task, 倘若此时线程池中有空闲的线程尝试读取 SynchronousQueue的task, 即调用了SynchronousQueue的poll(), 那么主线程将该task交给空闲线程. 否则执行(2)当线程池为空或者没有空闲的线程, 则创建新的线程执行任务.执行完任务的线程倘若在60s内仍空闲, 则会被终止. 因此长时间空闲的CachedThreadPool不会持有任何线程资源.关闭线程池遍历线程池中的所有线程,然后逐个调用线程的interrupt方法来中断线程.关闭方式 - shutdown将线程池里的线程状态设置成SHUTDOWN状态, 然后中断所有没有正在执行任务的线程.关闭方式 - shutdownNow将线程池里的线程状态设置成STOP状态, 然后停止所有正在执行或暂停任务的线程. 只要调用这两个关闭方法中的任意一个, isShutDown() 返回true. 当所有任务都成功关闭了, isTerminated()返回true.ThreadPoolExecutor源码详解几个关键属性内部状态其中AtomicInteger变量ctl的功能非常强大: 利用低29位表示线程池中线程数,通过高3位表示线程池的运行状态:RUNNING: -1 << COUNT_BITS,即高3位为111,该状态的线程池会接收新任务,并处理阻塞队列中的任务;SHUTDOWN: 0 << COUNT_BITS,即高3位为000,该状态的线程池不会接收新任务,但会处理阻塞队列中的任务;STOP : 1 << COUNT_BITS,即高3位为001,该状态的线程不会接收新任务,也不会处理阻塞队列中的任务,而且会中断正在运行的任务;TIDYING : 2 << COUNT_BITS,即高3位为010, 所有的任务都已经终止;TERMINATED: 3 << COUNT_BITS,即高3位为011, terminated()方法已经执行完成任务的执行execute –> addWorker –>runworker (getTask)线程池的工作线程通过Woker类实现,在ReentrantLock锁的保证下,把Woker实例插入到HashSet后,并启动Woker中的线程。 从Woker类的构造方法实现可以发现: 线程工厂在创建线程thread时,将Woker实例本身this作为参数传入,当执行start方法启动线程thread时,本质是执行了Worker的runWorker方法。 firstTask执行完成之后,通过getTask方法从阻塞队列中获取等待的任务,如果队列中没有任务,getTask方法会被阻塞并挂起,不会占用cpu资源;execute()方法ThreadPoolExecutor.execute(task)实现了Executor.execute(task)为什么需要double check线程池的状态?在多线程环境下,线程池的状态时刻在变化,而ctl.get()是非原子操作,很有可能刚获取了线程池状态后线程池状态就改变了。判断是否将command加入workque是线程池之前的状态。倘若没有double check,万一线程池处于非running状态(在多线程环境下很有可能发生),那么command永远不会执行。addWorker方法从方法execute的实现可以看出: addWorker主要负责创建新的线程并执行任务 线程池创建新线程执行任务时,需要 获取全局锁:Worker类的runworker方法继承了AQS类,可以方便的实现工作线程的中止操作;实现了Runnable接口,可以将自身作为一个任务在工作线程中执行;当前提交的任务firstTask作为参数传入Worker的构造方法;一些属性还有构造方法:runWorker方法是线程池的核心:线程启动之后,通过unlock方法释放锁,设置AQS的state为0,表示运行可中断;Worker执行firstTask或从workQueue中获取任务:进行加锁操作,保证thread不被其他线程中断(除非线程池被中断)检查线程池状态,倘若线程池处于中断状态,当前线程将中断。执行beforeExecute执行任务的run方法执行afterExecute方法解锁操作通过getTask方法从阻塞队列中获取等待的任务,如果队列中没有任务,getTask方法会被阻塞并挂起,不会占用cpu资源;getTask方法下面来看一下getTask()方法,这里面涉及到keepAliveTime的使用,从这个方法我们可以看出线程池是怎么让超过corePoolSize的那部分worker销毁的。注意这里一段代码是keepAliveTime起作用的关键:
allowCoreThreadTimeOut为false,线程即使空闲也不会被销毁;倘若为ture,在keepAliveTime内仍空闲则会被销毁。如果线程允许空闲等待而不被销毁timed == false,workQueue.take任务: 如果阻塞队列为空,当前线程会被挂起等待;当队列中有任务加入时,线程被唤醒,take方法返回任务,并执行;如果线程不允许无休止空闲timed == true, workQueue.poll任务: 如果在keepAliveTime时间内,阻塞队列还是没有任务,则返回null;任务的提交submit任务,等待线程池execute执行FutureTask类的get方法时,会把主线程封装成WaitNode节点并保存在waiters链表中, 并阻塞等待运行结果;FutureTask任务执行完成后,通过UNSAFE设置waiters相应的waitNode为null,并通过LockSupport类unpark方法唤醒主线程;在实际业务场景中,Future和Callable基本是成对出现的,Callable负责产生结果,Future负责获取结果。Callable接口类似于Runnable,只是Runnable没有返回值。Callable任务除了返回正常结果之外,如果发生异常,该异常也会被返回,即Future可以拿到异步执行任务各种结果;Future.get方法会导致主线程阻塞,直到Callable任务执行完成;submit方法AbstractExecutorService.submit()实现了ExecutorService.submit() 可以获取执行完的返回值, 而ThreadPoolExecutor 是AbstractExecutorService.submit()的子类,所以submit方法也是ThreadPoolExecutor`的方法。通过submit方法提交的Callable任务会被封装成了一个FutureTask对象。通过Executor.execute方法提交FutureTask到线程池中等待被执行,最终执行的是FutureTask的run方法;FutureTask对象public class FutureTask<V> implements RunnableFuture<V> 可以将FutureTask提交至线程池中等待被执行(通过FutureTask的run方法来执行)内部状态内部状态的修改通过sun.misc.Unsafe修改get方法内部通过awaitDone方法对主线程进行阻塞,具体实现如下:
如果主线程被中断,则抛出中断异常;判断FutureTask当前的state,如果大于COMPLETING,说明任务已经执行完成,则直接返回;如果当前state等于COMPLETING,说明任务已经执行完,这时主线程只需通过yield方法让出cpu资源,等待state变成NORMAL;通过WaitNode类封装当前线程,并通过UNSAFE添加到waiters链表;最终通过LockSupport的park或parkNanos挂起线程;run方法FutureTask.run方法是在线程池中被执行的,而非主线程通过执行Callable任务的call方法;如果call执行成功,则通过set方法保存结果;如果call执行有异常,则通过setException保存异常;任务的关闭shutdown方法会将线程池的状态设置为SHUTDOWN,线程池进入这个状态后,就拒绝再接受任务,然后会将剩余的任务全部执行完shutdownNow做的比较绝,它先将线程池状态设置为STOP,然后拒绝所有提交的任务。最后中断左右正在运行中的worker,然后清空任务队列。
更深入理解为什么线程池不允许使用Executors去创建? 推荐方式是什么?线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors各个方法的弊端:newFixedThreadPool和newSingleThreadExecutor: 主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。newCachedThreadPool和newScheduledThreadPool: 主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。推荐方式 1首先引入:commons-lang3包推荐方式 2首先引入:com.google.guava包推荐方式 3spring配置线程池方式:自定义线程工厂bean需要实现ThreadFactory,可参考该接口的其它默认实现类,使用方式直接注入bean调用execute(Runnable task)方法即可配置线程池需要考虑因素从任务的优先级,任务的执行时间长短,任务的性质(CPU密集/ IO密集),任务的依赖关系这四个角度来分析。并且近可能地使用有界的工作队列。性质不同的任务可用使用不同规模的线程池分开处理:CPU密集型: 尽可能少的线程,Ncpu+1IO密集型: 尽可能多的线程, Ncpu*2,比如数据库连接池混合型: CPU密集型的任务与IO密集型任务的执行时间差别较小,拆分为两个线程池;否则没有必要拆分。监控线程池的状态可以使用ThreadPoolExecutor以下方法:getTaskCount() Returns the approximate total number of tasks that have ever been scheduled for execution.getCompletedTaskCount() Returns the approximate total number of tasks that have completed execution. 返回结果少于getTaskCount()。getLargestPoolSize() Returns the largest number of threads that have ever simultaneously been in the pool. 返回结果小于等于maximumPoolSizegetPoolSize() Returns the current number of threads in the pool.getActiveCount() Returns the approximate number of threads that are actively executing tasks.参考文章《Java并发编程艺术》https://www.jianshu.com/p/87bff5cc8d8chttps://blog.csdn.net/programmer_at/article/details/79799267https://blog.csdn.net/u013332124/article/details/79587436https://www.journaldev.com/1069/threadpoolexecutor-java-thread-pool-example-executorservice由于问答代码块插入受限,部分代码未完全展示,若有需要可阅读原文:戳我阅读原文
如何快速入门面向对象编程?
谢邀!入门OOP大致有这样两个方面,一是理解OOP类的代码编写,一是理解对象的概念。
关于类和编码封装,继承和多态都是类的基本概念。(注意不是对象)掌握这些概念对理解和运用类非常重要。可以通过一些编程练习获得对这些概念的直观认识。编程语言推荐使用Java或者C#。这两种语言比较严谨地运用了类的概念,比较适合用来学习OOP。C++虽然也是OOP的语言,但语法过于复杂,不适合入门级学习使用。在对类和编码有了一定程度的理解之后,就要攻克OOP的难点,也就是对象的概念了。
关于对象教科书上喜欢用小猫小狗和动物之类的关系形容对象。这么形容倒也没有错误。但是,它造成了一种错觉,似乎是对象和类有一种一一对应的关系。实际上在OOP中对象可以是一个过程,也可以是一种结构,还可以是一组功能。这些对象往往需要用一组类和它们之间巧妙的组合来实现。而类也只不过是对象的代码实现而已。
举个例子一个增删改查的程序,它的流程是先查,然后增删改输入,然后增删改确认,最后提示增删改的结果。我们希望为这样的流程建个模版,保证所有的处理都遵循这一流程。首先,这个流程中,最基本的是增删改查其中的一个操作,为它做一个抽象类叫Action。Action除了做一次操作以外还要去调用下一个操作。所以,要有一个方法DoNext。我们还需要用另一个类,定义输入确认结果这一子流程。这个类里面要聚合三次操作。先查后操作要求我们还要用一个类来聚合一次检索和前面的子流程。在这里我只想说明复杂对象的概念,具体怎么用类来做定义就不啰嗦了。真正的实装中,上面的例子大概需要十几个类才能组合出来。
关于设计模式设计模式提供了很多对象实现的思路。可以通过学习设计模式理解对象的概念,并掌握一些用类实现的技巧。前面的例子就会用到抽象工厂模式。因此,设计模式也是OOP入门的必修课。


还没有评论,来说两句吧...