Java线程池实现原理之自定义线程池(一)

1.队列的概念

谈到多线程先讲下队列的概念,之后的多线程学习会用到此类知识。

队列分为:阻塞式队列(有界)、非阻塞式队列(无界),遵循着先进先出、后进后出的原则。
阻塞队列与非阻塞队列区别:
  1.非阻塞式队列超出队列总数会丢失。
  2.阻塞式队列超出总数会进入等待(等待时间=设置超时时间)。
  3.获取队列方面:非阻塞式队列,如果为空返回null。阻塞式队列,如果为空也会进入等待。
非阻塞式队列ConcurrentLinkedDeque
 1 //非阻塞式队列 无界(可以声明无限个队列)
 2     public static void test1(){
 3 
 4         ConcurrentLinkedDeque<Object> objects = new ConcurrentLinkedDeque<>();
 5         objects.offer("java001");
 6         objects.offer("java002");
 7 
 8         System.out.println("队列总数:"+objects.size());
 9 
10         //建议:获取队列之后删除
11         System.out.println("获取队列但不删除:"+objects.peek());
12         System.out.println("获取队列但不删除,队列总数:"+objects.size());
13         System.out.println("获取队列删除:"+objects.poll());
14 
15         //非阻塞式队列,如果为空返回null
16         System.out.println(objects.poll());
17         System.out.println(objects.poll());
18         System.out.println(objects.poll());
19         System.out.println("获取队列删除,队列总数:"+objects.size());
20     }
阻塞式队列ArrayBlockingQueue
 1 //阻塞式队列
 2     public static void test2() throws InterruptedException {
 3 
 4         long startTime=System.currentTimeMillis();
 5         ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);
 6         arrayBlockingQueue.offer("A001",3, TimeUnit.SECONDS);
 7         arrayBlockingQueue.offer("A002",3, TimeUnit.SECONDS);
 8 
 9         //阻塞式队列超出总数等待(等待时间=设置超时时间)
10         arrayBlockingQueue.offer("A003",3, TimeUnit.SECONDS);
11         arrayBlockingQueue.offer("A004",1, TimeUnit.SECONDS);
12         arrayBlockingQueue.offer("A005",1, TimeUnit.SECONDS);
13 
14         System.out.println("队列总数:"+arrayBlockingQueue.size());
15         System.out.println(arrayBlockingQueue.poll());
16         System.out.println(arrayBlockingQueue.poll());
17         System.out.println(arrayBlockingQueue.poll());
18         //阻塞式队列,如果为空也会等待。
19         System.out.println(arrayBlockingQueue.poll(1, TimeUnit.SECONDS));
20         System.out.println("队列剩余总数:"+arrayBlockingQueue.size());
21 
22         System.out.println("耗时:"+ (System.currentTimeMillis() - startTime)/1000 +"秒");
23 
24     }

2.线程池

线程池好处:
      1.降低资源 => 重复利用机制 (降低创建线程和销毁线程)
      2.提高响应效率 => 当任务到达时,任务可以不需要等待去创建线程就可以执行
      3.方便管理 => 无限创建线程消耗资源、降低系统稳定性。使用线程池可以统一分配、调优、监控。
线程与任务的区别:
      可以把线程理解成一个工作人员。而任务就是这个工作人员干的活。比如,餐厅的工作人员在为顾客传菜,传菜就是个任务。

      Java中线程就是Thread类或其子类的一个实例。
      也就是说你不必关注线程对象是用哪种方法创建的。在此基础上,线程所执行的代码,即run方法中的代码所实现的处理逻辑,
      比如读取数据库中的一条记录,就是一个任务。因此,所谓任务是一个相对的概念。一个任务可以是读取数据库中的一条记录,
      也可以是FTP传输一批文件,FTP传输一个文件……
 1 //创建线程四种方式:
 2     //1.可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
 3     //2.定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
 4     //3.可定时线程池,支持定时及周期性任务执行。
 5     //4.单例线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
 6     public static void test1() {
 7 
 8         //1.可缓存、定时、定长、单例
 9         ExecutorService executorService = Executors.newCachedThreadPool();
10         for (int i = 0; i <10 ; i++) {
11             final int i1 = i;
12             executorService.execute(new Runnable() {
13                 @Override
14                 public void run() {
15                     System.out.println(Thread.currentThread().getName()+",i:"+ i1);
16                 }
17             });
18         }
19 
20     }
21 
22     public static void test2() {
23 
24         //2.可定长线程,核心线程5个,最多创建5个线程 (只会创建5个线程,其他线程共享这5个线程)
25         ExecutorService executorService = Executors.newFixedThreadPool(5);
26         for (int i = 0; i <10 ; i++) {
27             final int i1 = i;
28             executorService.execute(new Runnable() {
29                 @Override
30                 public void run() {
31                     System.out.println(Thread.currentThread().getName()+",i:"+ i1);
32                 }
33             });
34         }
35     }
36 
37     public static void test3() {
38 
39         long l = System.currentTimeMillis();
40         //3.可定时线程 =>核心线程数3 (延迟三秒执行)
41         ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
42         for (int i = 0; i <10 ; i++) {
43 
44             final int i1 = i;
45             scheduledExecutorService.schedule(new Runnable() {
46                 @Override
47                 public void run() {
48                     System.out.println(Thread.currentThread().getName()+",i:"+ i1);
49                     System.out.println("耗时:"+ (System.currentTimeMillis() -l)/1000 +"秒" );
50                 }
51             },3, TimeUnit.SECONDS);
52         }
53 
54 
55 
56     }
57 
58     public static void test4() {
59 
60         //4.单例线程 =>核心线程数1 最大线程数1
61         ExecutorService executorService = Executors.newSingleThreadExecutor();
62         for (int i = 0; i <10 ; i++) {
63             final int i1 = i;
64             executorService.execute(new Runnable() {
65                 @Override
66                 public void run() {
67                     System.out.println(Thread.currentThread().getName()+",i:"+ i1);
68                 }
69             });
70         }
71     }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏君赏技术博客

建议大型项目用上Try Catch建议大型项目用上Try Catch

我们在平时项目做功能的时候,经常会遇到崩溃的情况。如果是我们在开发测试阶段,我们可以找到原因修复。但是遇到已经上线,出现这种问题。要么使用JSPatch进行热修...

9010
来自专栏java一日一条

2017年高频率的互联网校园招聘面试题

参加了2017年校招,面试了阿里、百度、腾讯、滴滴、美团、网易、去哪儿等公司,个人是客户端 Android 方向,总结了面试过程中频率出现较高的题目,希望对大家...

18320
来自专栏程序猿DD

Spring Boot使用@Async实现异步调用:使用Future以及定义超时

之前连续写了几篇关于使用 @Async实现异步调用的内容,也得到不少童鞋的反馈,其中问题比较多的就是关于返回 Future的使用方法以及对异步执行的超时控制,所...

24830
来自专栏FreeBuf

缓冲区溢出攻击初学者手册(更新版)

说明 之前版本翻译质量不佳,本人赵阳在这里对本文的读者表示深深的歉意。由于本人的疏忽和大意导致您不能很好的读完这篇文章,同时也对原文内容进行了破坏,也对IDF和...

30290
来自专栏FreeBuf

Windows内核漏洞CVE-2016-0143分析

0x00 背景 4月20日,Nils Sommer在exploitdb上爆出了一枚新的Windows内核漏洞PoC。该漏洞影响所有版本的Windows操作系统,...

24060
来自专栏程序员维他命

YYCache 源码解析(一):使用方法,架构与内存缓存的设计

YYCache是国内开发者ibireme开源的一个线程安全的高性能缓存组件,代码风格简洁清晰,阅读它的源码有助于建立比较完整的缓存设计的思路,同时也能巩固一下双...

41420
来自专栏zhisheng

0Day技术分析-4-堆溢出原理

《0Day技术分析》系列文章已经全部推送完毕,需要的电子稿的请加QQ1041218129(备注好需求),也可以直接在公众号查看文章目录。 堆溢出原理 1 堆的工...

52060
来自专栏大闲人柴毛毛

Java并发编程的艺术(七)——Executors

Executors框架简介 Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架...

37450
来自专栏大内老A

如何让普通变量也支持事务回滚?

有一次和人谈起关于事务的话题,谈到怎样的资源才能事务型资源。除了我们经常使用的数据库、消息队列、事务型文件系统(TxF)以及事务性注册表(TxR)等,还有那些资...

18880
来自专栏微信公众号:Java团长

从并发编程到分布式系统——如何处理海量数据(上)

在这里想写写自己在学习并发处理的学习思路,也会聊聊自己遇到的那些坑,以此为记,希望鞭策自己不断学习、永不放弃!

9810

扫码关注云+社区

领取腾讯云代金券