java线程概述
时间:2010-10-19 来源:consy
使用java线程方法有两种
一是显式的创建执行线程,创建执行线程有两种方法
创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。例如,计算大于某一规定值的质数的线程可以写成:
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
然后,下列代码会创建并启动一个线程:
PrimeThread p = new PrimeThread(143);
p.start();
创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。采用这种风格的同一个例子如下所示:
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
然后,下列代码会创建并启动一个线程:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
每个线程都有一个标识名,多个线程可以同名。如果线程创建时没有指定标识名,就会为其生成一个新名称。
一般不推荐使用第一种直接继承Thread的方式,而是使用Runnable接口来创建线程
使用线程的第二个方法是采用线程池
线程相对与进程来谁说虽说代价小得多,但也需跟操作系统交互还是有一定代价的,特别是有时候一个新线程可能只需完成一个很小的任务执行很少的代码,这样的线程声明周期比较短,还是有一定的开销的,这时候就可以使用线程池。一个线程池中可有多个已经创建好随时准备运行的空闲线程。将Runnable对象交给线程池,线程池其中的一个线程就负责运行这个Runnable的run方法。而当run方法运行完毕是线程不一定立即死亡,而是继续等待下一次的服务。
使用线程池的另一个好处是可以控制同一进程中线程并行的数目。采用第一种方式显式创建线程的话如果有10个就会有10个线程并发执行有100个就会有100个线程并发执行,如果1000个10000个那么...虚拟机估计罢工了。采用线程池的话可以创建一个拥有最大线程数目的线程池,最多只能并发执行固定数目的线程多出来的线程只能等待正在执行的线程退出。在java.util.concurrent包中有个类Executors,该类有以下五个静态方法:
1.newCachedThreadPool():创建一个缓冲线程池,必要是创建新线程,线程执行任务后不马上注销,而是缓存60秒钟,以便执行新的其他的任务。
2.newFixedThreadPool():创建一个固定数目的线程池(池里总是有那么多水,既不会蒸发也不会流入..),线程池总是会保持指定数目的线程而不管是否有线程空闲还是线程不够,提交到线程池的任务太多的话多余的只能等,这样可以控制并发线程数目。
3.newSingleThreadPExecutor():创建只有一个线程的”线程池“(池里只有一滴水啊),所有提交到此种线程池的任务都要排队等待这个唯一的线程去执行。
4.newScheduledThreadPool():用于固定执行而构建的固定线程池,用于替代java.util.Timer
5.newSingleThreadScheduleExecutor():用于预定执行而构建的单线程池
上述五个方法都会返回一个实现了ExecutorService接口的ThreadPoolExecutor类的对象。向线程池提交任务的方法为:将一个实现Runnable或Callable接口的对象提交给ExecutorService:
Future<?> submit(Runable task)
Future<T> submit(Runable task, T result)
Future<t> submit(Callable<T> task)
线程会在适当的时候尽早执行提交的任务,调用submit时会返回一个Future对象,用以查询该任务的状态,或者取消该任务。
第一个submit方法提交一个Runable对象返回一个Future<?>,可使用该对象调用isDone、cancel、或者isCancelled来查询任务状态。但是此Future对象的get方法在任务完成的时候知识简单的返回null
第二个版本的submit方法同样提交一个Runable对象,并且返回Future的get方法在任务完成的时候返回传入的result对象
第三个submit方法提交一个Callable对象,并且返回的Future对象将在计算结构、准备好的时候得到它。
当想要注销一个线程池,可调用shutdown方法,该方法启动该线程池的关闭序列。此时线程池并不是马上就壮烈牺牲了线程也没了,而是等待所以任务都完成以后,线程池中的线程才会死亡,被关闭的执行器不再接受新任务。也可以调用shutdownNow,此时线程池会取消正在排队等待处理的任务并且试图中断正在执行的线程。
使用线程池的步骤如下:
1)调用Executors类中的静态方法newCachedThreadPool或newFixedThreadPool,创建一个新的线程池并返回一个执行器对象ExecutorService(ThreadPoolExecutor)
2)调用执行器对象的submit提交Runnable或者Callable对象
3)如果想要取消一个任务,或如果提交Callable对象,那就要保存返回的Future对象
4)当不再提交任务任务时,调用shutdown