下面我们再说说线程池。大家知道就是线程它在Java里面很方便
NewThread=Start就可以了,那么我们有的时候可以有大量的这个线程。
那么是不是线程越多,计算机运行就快了?并不是这样的。我们知道
线程它主要解决的是一些独立的这些任务,让它并发的能够同时运行。
但是呢,每开一个线程对象,
那系统呢就要为这个线程建很多的,比如说,环境,建这些
相应的机制。所以这样的话它实际上线程的开销是很大的。
所以我们说并不是线程越多,程序运行呢越快。
这个说法是不对的,啊,这个说法事不对的。那我们有一个办法就是 使用线程池。线程池呢我们可以简单理解的就是
我们同时开好多线程,这个 线程呢我们用的时候,
我们用一个线程让它来执行一些的任务。这个线程对象
我们下一次呢如果再有别的任务,这个线程对象呢并没有销毁掉,
然后呢下次新的任务还是用这个线程去执行。那么我们开一系列的、
一定数量的这个线程放到那里,这个呢就称为线程池。所以,呃,
线程池相关的也有很多类别说Excuter Service接口,
还有呢它的实现ThreadPoolExecutor这个类。
另外呢它还有Excercutors这个工具类。
我们很方便的用,那就常见的一个用法呢就是用Executors
Service的方法叫NewCacheThreadPool,创建这样一个线程池。
这个线程池呢然后用Execute的方法 来执行,当然执行的也是一个Runnable,也就是run方法。
所以这个Executor呢它在执行别的这个事情,那么很多的事情呢都可以交给 这样一个线程池来执行。
我们下面看看这个例子,请看这里有一系列的Runnable对象,
它的任务呢就是做一系列Run方法里面做一系列的事情,这里呢就是显示一些数据。
然后这些线程我们 并不需要假设有很多线程的话,我们并不需要
同时开那么多线程。那我们可以用一个线程池, 这个线程池呢就是newCacheThreadPool
创建一个系统默认的一个线程池。
这个线程池呢然后我们把这个任务交给它就可以了。
Execute的这一个Runnable,Execute的这一个Runnable或者- Execute的另一个Runnable。
然后如果这些线程指令都执行完了我们可以
pool.shutdown,所以线程池的好处呢就是可以多个线程共用
一定数量的线程,而不用,假设我们有一千个任务,
那我们并不需要开一千个线程,这就是线程池的一个好处。
这也是我们在实际编程里面经常用到的。
另外一个工具类呢就是Timer,这个Timer有两个Timer;
一个是java.util.Timer,这个是在
工具类里头,呃,它是,这个Timer我们把它翻译成计时器,
实际上呢就是重复每隔一定的时间就重复做某一件事情。
那这是一个,就是普通的Timer。另外呢, 在这个界面里头javax.swing 里面
也有一个Timer类,这个呢它也是重复执行着每隔一定时间重复执行的任务。
这两个类呢用起来也是特别方便。
当然它底层实际上它是用一个线程,变成一个线程是循环的
执行一定的任务。我们下面看看这个代码,
请看这里,这里有一个Timer对象,
这个Timer对象它用了一个schedule, 啊,schedule这么一个就是
每隔一定时间执行的任务。这个任务呢,是一个mytask,
是一个TimerTask这样的一个对象,里面呢也有一个run方法。
那每隔一定的时间执行一个任务,但这里呢 我们是每隔一段时间显示一下当前时间,我们运行一下。
你会发现它每隔几秒钟重复的执行。
但对我们来说,我们没有明显的写出一个线程, 但实际上底层呢就是一个线程。我们下面再看一个例子;
这个例子呢是用在运用在swing里面的Timer类。
这里面怎么用呢?就是我们有一个界面对象,然后呢我们new一个Timer。
这个Timer呢也给一个时间间隔,比如说这是1000毫秒,也就是一秒钟。
然后呢,里面需要一个执行的任务,这个是 x in performe的,这里呢我们那么来写就更方便。
就是一个参数e,当然这里没有用到,然后一个箭头。然后执行的语句呢
是setTitle,也就是说把那个 窗口的标题之类的当前的时间
然后用Timer.start就开始执行了。
但这底下,底层呢它也是用线程来实现。
我们运行一下,请看这里,那这里的这个Time每隔一定的
时间就自行的任务,现在的任务是现实当前的时间到这个标题上面。
可见呢这个Timer用起来还是很方便的。
我们在使用线程呢,我们前面已经提到使用 变量的时候要注意原则变量,使用集合了之后要用并发的集合。
然后呢,还有一个问题也特别重要,
就是在线程里面如果要更新图形化的界面的的话
就需要调用一个特殊的方法--SwingUtilites.invokeLater,
这是为什么呢?我们知道呢 界面里面它要显示,比如说要改变标签上面的文本啊,
比如说要画图啊等等,所有的做这些界面相关的这个事情呢
我们都需要在图形化界面它统一的去处理。否则的话,
那么你在那个线程去处理,这里跟界面的显示可能就不同步,
就会造成混乱。所以呢,从JDK实际上从1.2开始以后
它都要求不能够直接在一个 线程里面去更新这个界面。
我们就需要用SwingUtilites.
invokeLater,这里面也要跟一个Runnable对象,也就是Run方法。
所以,当然它用起来也是比较简单,我们只需, 只不过要注意这个,嗯,SwingUtiltes.invokeLater
来做一些界面的这个更新。最常见的是,比如说我们有一个图形化的界面, 然后呢,它里面做一些任务,比如说:下载。
我们下载完了,想通知这个界面,想在界面上显示说下载已经完成,显示那个标签。
那么你不能在那个线程里面写一条语句就说,设定,Setting成什么text;
不能这么做,必须把它放到一个invokeLater里边去。我们还是把
前面我们举过的这个例子,嗯,再打开看一下。
请看这个例子,我们有很多线程,这些线程呢 它都要更新界面,当然现在的界面呢实在界面上画图啦!
那我们做的时候,这个调用画图是在线程里调用的,
是在线程里调用的,我们就要SwingUtilites.invokeLater,
然后这是一个Runnable对象,我这边有那么的表示也就是不带
参数,然后一个箭头,然後这里面。然后,我们就不能直接这么写,不能直接写这个
线程里头。这是因为呢, 我们的这些任务呢都要交给Swing
主线程它来统一的去执行我们这些界面的工作。