java自己实现线程池,java中线程池的创建与使用
Java代码构建线程池-鱼河专栏-博客频道-CSDN。网
Java代码构建了一个线程池。
2005-10-26 16:42
62人阅读
评论(0)
收集
这个示例报告程序包含三个类。第一个是TestThreadPool类,这是一个用于模拟客户端请求的测试程序。当您运行它时,系统将首先显示线程池的初始化信息,然后提示您从键盘输入一个字符串并按回车键。这时,你会发现屏幕上显示的信息告诉你某个线程正在处理你的请求。如果您快速地逐行输入一个字符串,那么您会发现线程池中的线程会不断地被唤醒来处理您的请求。在这个例子中,我创建了一个有10个线程的线程池。如果线程池中没有可用的线程,系统会用相应的警告信息提示您。但是如果你等一会儿,然后你会发现屏幕会提示一个又一个线程进入睡眠状态。此时,您可以再次发送新的请求。
第二个类是ThreadPoolManager类。顾名思义,它是一个用于管理线程池的类。它的主要职责是初始化线程池,并将不同的线程分配给客户端的请求进行处理。如果线程池已满,它会给你一个警告消息。
最后一个类是SimpleThread类,它是Thread类的子类。它真正处理客户的请求。当示例程序初始化时,SimpleThread处于睡眠状态,但如果它接收到ThreadPoolManager类发送的调度信息,它将唤醒自己并处理请求。
让我们先来看看TestThreadPool类的源代码:
//TestThreadPool.java
1导入Java . io . *;
2
三
4公共类TestThreadPool
5 {
6公共静态void main(String[] args)
7 {
8尝试{
9 buffered reader br=new buffered reader(new InputStreamReader(system . in));
10串s;
11 ThreadPoolManager manager=new ThreadPoolManager(10);
12 while((s=br.readLine())!=空)
13 {
14个经理流程;
15 }
16 }catch(IOException e){}
17 }
18 }
因为这个测试程序使用了input-input类,所以JAVA的基本IO处理包是在第1行导入的。在第11行,我们创建了一个名为manager的类,它将一个值为10的参数传递给ThreadPoolManager类的构造函数,并告诉ThreadPoolManager类:我想要一个有10个线程的池,给我创建一个吧!第12行到第15行是一个无限循环,用来等待用户的键入,将键入的字符串保存在S变量中,调用ThreadPoolManager类的process方法来处理这个请求。
让我们进一步追溯到ThreadPoolManager类。下面是它的源代码:
//ThreadPoolManager.java
1导入Java . util . *;
2
三
4类ThreadPoolManager
5 {
六
7 private int maxThread
8公共向量向量;
9 public void setMaxThread(int thread count)
10 {
11 maxThread=threadCount
12 }
13
14公共线程池管理器(int threadCount)
15 {
16 setMaxThread(thread count);
17 System.out.println(启动线程池.);
18向量=新向量();
19 for(int I=1;i=10我)
20 {
21 simple thread thread=new simple thread(I);
22 vector.addElement(线程);
23 thread.start()。
24 }
25 }
26
27公共void进程(字符串参数)
28 {
29 int I;
30 for(I=0;I vector . size();我)
31 {
32 simple thread current thread=(simple thread)vector . element at(I);
33如果(!currentThread.isRunning())
34 {
35 system . out . println( Thread (I 1)正在处理:
论据);
36 currentThread.setArgument(参数);
37 currentThread.setRunning(真);
38返回;
39 }
40 }
41 if(i==vector.size())
42 {
43 System.out.println(池已满,下次再试。);
44 }
45 }
46 }//ThreadPoolManager类的结尾
我们先来关注一下这个类的构造函数,然后再来看它的process()方法。第16-24行是它的构造函数。首先,它为ThreadPoolManager类的成员变量maxThread赋值。maxThread表示它用于控制线程池中线程的最大数量。第18行初始化一个数组向量,用于存储所有SimpleThread类。这时候就充分体现了JAVA语言的优越性和艺术性:如果用C语言,至少要写100行代码才能完成vector的功能。而且C语言数组只能容纳统一类型的基本数据类型,不能容纳对象。好吧,我们长话短说。第19-24行的循环完成了这样一个功能:首先创建一个新的SimpleThread类,然后放入vector,最后用thread.start()启动线程。为什么要用start()方法启动线程?因为这是JAVA语言规定的,如果不使用,那么这些线程永远不会被激活,导致这个示例程序根本无法运行。
我们再来看看process()方法。第30-40行的循环依次从vector数组中选择SimpleThread线程,检查它是否处于活动状态(所谓活动状态是指这个线程是否在处理客户端的请求)。如果它是活动的,继续寻找向量数组中的下一项。如果vector数组中的所有线程都是活动的,它将打印出一条消息,提示用户稍后再试。相反,如果发现一个休眠线程,第35-38行将会处理它。它首先告诉客户端哪个线程将处理请求,然后将客户端的请求,即字符串参数,转发给SimpleThread类的setArgument()方法进行处理,并调用SimpleThread类的setRunning()方法唤醒当前线程处理客户端的请求。
也许你还不明白setRunning()方法是如何唤醒线程的,那么我们现在来看最后一个类:SimpleThread类,它的源代码如下:
//SimpleThread.java
1类SimpleThread扩展线程
2 {
3私有布尔runningFlag
4私有字符串参数;
5 public boolean isRunning()
6 {
7返回runningFlag
8 }
9公共同步void setRunning(布尔标志)
10 {
11 runningFlag=flag
12如果(标志)
13 this . notify();
14 }
15
16公共字符串getArgument()
17 {
返回this.argument
19 }
20 public void setArgument(String字符串)
21 {
22自变量=字符串;
23 }
24
25公共简单线程(int threadNumber)
26 {
27 runningFlag=false
28 system . out . println( thread thread number 已启动。);
29 }
30
31公共同步无效运行()
32 {
33尝试{
34 while(真)
35 {
36如果(!运行标志)
37 {
38 this . wait();
39 }
其他40个
41 {
42 system . out . println( processing get argument().“成交。”);
43睡眠(5000);
44 System.out.println(线程正在休眠.);
45 setRunning(假);
46 }
47 }
48 } catch(中断异常e){
49 System.out.println(中断);
50 }
51 }//运行结束()
52 }//类SimpleThread的结尾
如果你不懂JAVA的线程编程,我在这里简单解释一下。JAVA有一个名为Thread的类。如果要创建线程,必须从Thread类继承,还必须实现Thread类的run()接口。要激活一个线程,必须调用它的start()方法,这个方法会自动调用run()接口,所以用户必须在so我们如何控制线程的睡眠和唤醒中调用start()接口?其实很简单。JAVA语言为所有对象内置了wait()和notify()方法。当一个线程调用wait()方法时,线程进入睡眠状态,就像它在当前代码处停止一样,它不会继续执行它下面的代码。当调用notify()方法时,下面的代码将从调用wait()方法的那一行继续执行,这有点像在编译器中。以这个节目为例。当在第38行调用wait()方法时,线程在第38行停止,就像被冻结了一样。如果我们在第13行调用notify(),线程将从第38行唤醒,并继续执行第39行的代码。
通过以上,我们现在就不难理解SimpleThread类了。第9-14行通过设置一个标志runningFlag来激活当前线程,第25-29行是SimpleThread类的构造函数,用来告诉客户端启动哪个进程。第31-50行是我实现的run()接口。它实际上是一个无限循环。在循环中,首先判断flag runningFlag。如果no runningFlag为false,那么线程将处理睡眠状态,否则第42-45行将进行真正的处理:首先打印用户键入的字符串,然后睡眠5秒钟。为什么要睡5秒?如果不加这段代码,因为电脑的处理速度远远快于你键盘的输入速度,你看到的永远是1号线程处理你的请求,所以演示效果达不到。最后一行45调用setRunning()方法让线程休眠并等待新的请求。
最后需要注意的是,如果在一个方法中调用wait()和notify()函数,必须将这个方法设置为synchronized,也就是synchronized,否则编译时会报错,得到一个莫名其妙的消息:“当前线程不是所有者”(当前线程不是所有者)。分享到:上一篇:简单线程缓冲池的实现
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。