孔乙己:跟我学做菜……不,多线程吧!
孔乙己一到店,所有上机的人便都看着他笑,有的叫道,“孔乙己,你的github上又添star了”。
他不回答,对柜里说,“开个机子,再来个9块9套餐。”便排出九行大钱。“现钱!”
他们又故意高声的嚷道:“你一定又FQ了吧。”
孔乙己睁大眼睛说,“你怎么这样凭空污人家清白……”
“什么清白?我前两天亲眼见你翻了P站的墙,吊着打。”
孔乙己便涨红了脸,额上的青筋条条绽出,争辩道,“翻P站不能算翻……P站!……程序员儿的事,能算翻么?”
接连便是难懂的话,什么“P站学技术”,“G站交友”这类,引得众人都哄笑起来;店内外充满了快活的空气。
有一回他对我说道:“姚毛毛,你写过程序么?”
我略略一点头。
他说,“写过程序……我便考一考你。多线程怎么创建的?”
我想,讨饭一样的人,也配考我么?便回过脸去,不再理会。
孔乙己等了很久,很恳切的说道,“不能写罢?……我教给你,记着!这些方法,将来做CTO的时候,写代码要用。”
我暗想我和CTO的等级还很远呢,而且我们CTO从来不写代码;又好笑,又不耐烦,懒懒的答他道,“谁要你教,不就是new Thread么?”
孔乙己显出极高兴的样子,将两个指头敲着柜台,点头说,“对呀对呀!……线程有5种创建方法,你知道么?线程池你知道吗?线程等待知道吗?”
孔乙己刚用指头敲了敲键盘,想在IDE中写几行代码,见我毫不热心,便又叹一口气,显出极惋惜的样子。
我见他这模样,就心生了几分怜悯,应了一声,“有5种方法啊,你说来听听。”
孔乙己立时精神一振,便把左右手两个手指头重新搭在了键盘上。
“lamada表达式知道吧?java8的新特性,用这种写法贼爽。”孔乙己涨红了脸,吐了口唾沫,“你看这样 new Thread就行。”
说着,写出下面这行代码。
new Thread(() -> {
// do something
}).start();
“这不就是new Runnable()的简写嘛。”我撇撇嘴,便写给他看。
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// do something
}
});
孔乙己摇了摇头,“是耶?非耶?lamada的效率可比它高呢。”
“那还有三种呢?”我看着孔乙己满足的神情,不忍心打破,便又顺着他的话问下去。
“其他的三种分别是extends Thread、implements Runnable、implements Callable,Callable要跟FutureTask一起用,可以返回执行结果。”孔乙己粗短的手指便卖力的在键盘上敲了起来。
我已然不耐,没有心思看他的代码,只想早早把他打发,便说道,“那怎么做线程等待呢?真的有5种吗?”
孔乙己“呵呵”的笑了两声,像是被捏住喉咙的鸭子,“join你知道吧?还有门闩、栅栏、信号量你听过吗?就是这样写的……”
说着,写出CountDownLatch、CyclicBarrier、Semaphore这三个单词。
孔乙己写完得意地笑了,像极了那晚FQ到P站后的笑容。“后面这三个可是能在线程池运行中进行线程等待的。”
我疑惑道,“那还有一个呢”?
孔乙己愈发得意,“white true 加isTerminated 呀!”
while (true) {
if (threadPool.isTerminated()) {
System.out.println("线程池关闭");
break;
}
Thread.sleep(200);
}
嗨,学这么多有啥用呢?我暗想,这像你,腿也瘸了,头也秃了。只是我嘴上却说道,“那么,这线程池几种写法呢?”
孔乙己似乎拿起了架子。他摘下眼镜,哈了口气在上面,又擦了擦,才慢条斯理地说道,“主要就是两种线程类呢!其他的都是继承的。”
我随口搭了一声,“是ThreadPool跟ForkJoinPool么?”
孔乙己苍白的脸上泛起了不正常的红晕,“对的,对的。”说着,立马敲下了代码。
ExecutorService threadPool = null;
// 弹性缓存线程池
threadPool = Executors.newCachedThreadPool();
// 固定大小线程池
threadPool = Executors.newFixedThreadPool(3);
// 定时任务线程池
threadPool = Executors.newScheduledThreadPool(2);
// 单线程的线程池,只有一个线程在工作
threadPool = Executors.newSingleThreadExecutor();
// ThreadPool 默认线程池,可控制参数比较多
threadPool = new ThreadPoolExecutor();
// ForkJoinPool 默认线程池,少量线程、大量IO操作时使用
ForkJoinPool threadPool = new ForkJoinPool(5);
// ForkJoinPool的一种
ExecutorService workStealingPool = Executors.newWorkStealingPool(5);
孔乙己“啧啧”嘴,“其实仔细算起来是七种线程池呢!”
接着便又嘀咕起了“四种拒绝策略”、“三种阻塞队列”这些难懂的话。
我就这样站在柜上跟孔乙己聊了好些时候,掌柜的也不来拦我,毕竟孔乙己也是能带来快活空气的人儿呢。
就在临走的时候,孔乙己还说道,“你会用springboot吧?springboot里还有两种注解也可以创建多线程任务呢。”
我没再理会他,但听他说着“定时器@Scheduled注解”、“@Async异步线程注解”,瘸着腿,一高一低的,渐渐地走远了。
此后,便再也没看到孔乙己了,也偶尔听到来上机的客人说道,他是哪天FQ被人抓了,腿都给打折了。
到了年关,掌柜的还说“孔乙己还欠十九个钱呢!”
到第二年的端午,又说“孔乙己还欠十九个钱呢!”
到中秋却是没说了,再到年关还是没有见到他。
我到现在终于没有见——大约孔乙己的确死了。
文章首发公众号:姚毛毛的博客
这里有我的编程生涯感悟与总结,有Java、Linux、Oracle、mysql的相关技术,有工作中进行的架构设计实践和读书理论,有JVM、Linux、数据库的性能调优,有……
有技术,有情怀,有温度
欢迎关注我:姚毛毛& 妖生