700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > java基础:简单实现线程池

java基础:简单实现线程池

时间:2022-04-08 20:19:15

相关推荐

java基础:简单实现线程池

先上原理图:为了更好的在手机上显示,我重新把图画了一遍

上代码之前,要先补充一下线程池构造的核心几个点

线程池里的核心线程数与最大线程数

线程池里真正工作的线程worker

线程池里用来存取任务的队列BlockingQueue

线程中的任务task

本例实现简化了一些,只实现了BlockingQueue存放任务,然后每个worker取任务并执行,下面看代码

首先定义一个线程池ThreadExcutor

classThreadExcutor{//创建privatevolatilebooleanRUNNING=true;//所有任务都放队列中,让工作线程来消费privatestaticBlockingQueue<Runnable>queue=null;privatefinalHashSet<Worker>workers=newHashSet<Worker>();privatefinalList<Thread>threadList=newArrayList<Thread>();//工作线程数intpoolSize=0;//核心线程数(创建了多少个工作线程)intcoreSize=0;booleanshutdown=false;publicThreadExcutor(intpoolSize){this.poolSize=poolSize;queue=newLinkedBlockingQueue<Runnable>(poolSize);}publicvoidexec(Runnablerunnable){if(runnable==null)thrownewNullPointerException();if(coreSize<poolSize){addThread(runnable);}else{//System.out.println("offer"+runnable.toString()+""+queue.size());try{queue.put(runnable);}catch(InterruptedExceptione){e.printStackTrace();}}}publicvoidaddThread(Runnablerunnable){coreSize++;Workerworker=newWorker(runnable);workers.add(worker);Threadt=newThread(worker);threadList.add(t);try{t.start();}catch(Exceptione){e.printStackTrace();}}publicvoidshutdown(){RUNNING=false;if(!workers.isEmpty()){for(Workerworker:workers){worker.interruptIfIdle();}}shutdown=true;Thread.currentThread().interrupt();}//这里留个位置放内部类Worker}

然后定义一个内部类Worker,这个内部类Worker是用来执行每个任务的,在创建线程池后,往线程里添加任务,每个任务都是由Worker一个一个来启动的。

/***工作线程*/classWorkerimplementsRunnable{publicWorker(Runnablerunnable){queue.offer(runnable);}@Overridepublicvoidrun(){while(true&&RUNNING){if(shutdown==true){Thread.interrupted();}Runnabletask=null;try{task=getTask();task.run();}catch(InterruptedExceptione){e.printStackTrace();}}}publicRunnablegetTask()throwsInterruptedException{returnqueue.take();}publicvoidinterruptIfIdle(){for(Threadthread:threadList){System.out.println(thread.getName()+"interrupt");thread.interrupt();}}}

首先注意的一点,这个Worker是个内部类,是在线程池内声明的。

exec方法
Worker怎么工作

这个工作线程实例化的时候就先加入一个任务到队列中,也就是说在实例化这个工作线程时,这个工作线程也是一个任务被加入到线程池中。然后就是run方法,这个run方法是线程调start方法生成的线程,而Worker调的run方法并没有生成新的线程。就是一个循环,一直在不停的从队列中取任务,然后执行。可以看到,取队列的方法是take(),这个方法意思如果队列为空了,取不到数据时就阻塞队列。

然后看shutdown()

你每天辛勤的劳动着,突然接收到上面的命令,说活暂时不要接了,先停下来,当你还没搞清楚状况时,接着你的领导又把你开除了,说公司要倒了,你先下岗吧,一会我也得下岗了。这就是shutdown做的事,shutdown必须是主线程才能停止工作线程。

shutdown方法并不是用线程那种强制停止的搞法,而是先用一个标识符告诉工作线程,不要再接任务了。然后通知工作线程,你可以interrupt()了,当所有的线程停止后记得要把主线程也停掉,这样,一个简单任务的线程池就完成了。

让我们来测试一下:

/***Createdbywxwallon/6/7.*/publicclassTheadBlockedQ{publicstaticvoidmain(String[]args)throwsInterruptedException{ThreadExcutorexcutor=newThreadExcutor(3);for(inti=0;i<10;i++){excutor.exec(newRunnable(){@Overridepublicvoidrun(){System.out.println("线程"+Thread.currentThread().getName()+"在帮我干活");}});}excutor.shutdown();}}

输出结果为:

线程Thread-0在帮我干活线程Thread-2在帮我干活线程Thread-1在帮我干活线程Thread-0在帮我干活线程Thread-2在帮我干活线程Thread-2在帮我干活线程Thread-1在帮我干活线程Thread-0在帮我干活Thread-0interruptThread-1interruptThread-2interruptThread-0interruptThread-1interruptThread-2interruptThread-0interruptThread-1interruptThread-2interrupt

这当然是最简单实现,JDK的实现比这强大的多,而且还具备当工作线程处理不过来时,可以产生新的线程来处理任务,这个数量不能超过原先定义的最大线程数,而在本例中都没实现这些功能。

我相信当想了解一个模块的功能时,如果一开始就了解其中最核心的点,然后向外慢慢扩展,那么学习这个模块时一定能省下不少时间,而且理解将很深刻。希望这个简单线程池实现能让你有所领悟,以更加简单的方式了解线程池,了解了线程池,对于其他池化技术,原理都是相通的。

本文转自 zddnd 51CTO博客,原文链接:/13013666/1940090

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。