myThread2.start();
2、实现Runnable接口方式实现多线程
如果自己的类已经extends另一个类,就无法直接extends Thread,此时,必须实现一个Runnable接口,如下:
-
public class MyThread extends OtherClass implements Runnable {
-
public void run() {
-
System.out.println("MyThread.run()");
-
}
-
}

为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例:
-
MyThread myThread = new MyThread();
-
Thread thread = new Thread(myThread);
-
thread.start();

事实上,当传入一个Runnable target参数给Thread后,Thread的run()方法就会调用target.run(),参考JDK源代码:
-
public void run() {
-
if (target != null) {
-
target.run();
-
}
-
}

3、使用ExecutorService、Callable、Future实现有返回结果的多线程
ExecutorService、Callable、Future这个对象实际上都是属于Executor框架中的功能类。想要详细了解Executor框架的可以访问http://www.javaeye.com/topic/366591 ,这里面对该框架做了很详细的解释。返回结果的线程是在JDK1.5中引入的新特征,确实很实用,有了这种特征我就不需要再为了得到返回值而大费周折了,而且即便实现了也可能漏洞百出。
可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口。执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了,再结合线程池接口ExecutorService就可以实现传说中有返回结果的多线程了。下面提供了一个完整的有返回结果的多线程测试例子,在JDK1.5下验证过没问题可以直接使用。代码如下:
package problem01;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class MyCallable implements Callable<Object>{
private String taskNum;
MyCallable(String taskNum){
this.taskNum = taskNum;
}
public Object call(){
System.out.println(">>>"+taskNum+"任务启动");
Date dateTmp1 = new Date();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Date dateTmp2 = new Date();
long time = dateTmp2.getTime() - dateTmp1.getTime();
System.out.println(">>>"+taskNum+"任务终止");
return taskNum+"任务返回运行结果,当前时间【"+time+"毫秒】";
}
}
public class test{
public static void main(String args[]){
System.out.println("-----程序开始运行-------");
Date date = new Date();
int taskSize = 5;
//创建一个线程池
ExecutorService pool = Executors.newFixedThreadPool(taskSize);
//创建多个有返回值的任务
List<Future> list = new ArrayList<Future>();
for(int i=0;i<taskSize;i++){
Callable c = new MyCallable(i+" ");
//执行任务并获取Future对象
Future f = pool.submit(c);
list.add(f);
}
pool.shutdown();
//获取所有并发任务的运行结果
System.out.println("=============================================");
for(Future f:list){
try {
System.out.println(">>>"+f.get().toString());
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Date date2 = new Date();
System.out.println("---程序结束运行---,程序运行时间【"+(date2.getTime()
-date.getTime())+"毫秒】");
}
}
以下转载自http://www.iteye.com/topic/366591点击打开链接
Executor框架是指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等。
并发编程的一种编程方式是把任务拆分为一些列的小任务,即Runnable,然后在提交给一个Executor执行,Executor.execute(Runnalbe) 。Executor在执行时使用内部的线程池完成操作。
一、创建线程池
Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
public static ExecutorService newFixedThreadPool(int nThreads)
创建固定数目线程的线程池。
public static ExecutorService newCachedThreadPool()
创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
public static ExecutorService newSingleThreadExecutor()
创建一个单线程化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
Java代码 

-
Executor executor = Executors.newFixedThreadPool(10);
-
Runnable task = new Runnable() {
-
@Override
-
public void run() {
-
System.out.println("task over");
-
}
-
};
-
executor.execute(task);
-
-
executor = Executors.newScheduledThreadPool(10);
-
ScheduledExecutorService scheduler = (ScheduledExecutorService) executor;
-
scheduler.scheduleAtFixedRate(task, 10, 10, TimeUnit.SECONDS);
Executor executor = Executors.newFixedThreadPool(10);
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("task over");
}
};
executor.execute(task);
executor = Executors.newScheduledThreadPool(10);
ScheduledExecutorService scheduler = (ScheduledExecutorService) executor;
scheduler.scheduleAtFixedRate(task, 10, 10, TimeUnit.SECONDS);
二、ExecutorService与生命周期
ExecutorService扩展了Executor并添加了一些生命周期管理的方法。一个Executor的生命周期有三种状态,运行 ,关闭 ,终止 。Executor创建时处于运行状态。当调用ExecutorService.shutdown()后,处于关闭状态,isShutdown()方法返回true。这时,不应该再想Executor中添加任务,所有已添加的任务执行完毕后,Executor处于终止状态,isTerminated()返回true。
如果Executor处于关闭状态,往Executor提交任务会抛出unchecked exception RejectedExecutionException。
Java代码 

-
ExecutorService executorService = (ExecutorService) executor;
-
while (!executorService.isShutdown()) {
-
try {
-
executorService.execute(task);
-
} catch (RejectedExecutionException ignored) {
-
-
}
-
}
-
executorService.shutdown();
ExecutorService executorService = (ExecutorService) executor;
while (!executorService.isShutdown()) {
try {
executorService.execute(task);
} catch (RejectedExecutionException ignored) {
}
}
executorService.shutdown();
三、使用Callable,Future返回结果
Future<V>代表一个异步执行的操作,通过get()方法可以获得操作的结果,如果异步操作还没有完成,则,get()会使当前线程阻塞。FutureTask<V>实现了Future<V>和Runable<V>。Callable代表一个有返回值得操作。
Java代码 

-
Callable<Integer> func = new Callable<Integer>(){
-
public Integer call() throws Exception {
-
System.out.println("inside callable");
-
Thread.sleep(1000);
-
return new Integer(8);
-
}
-
};
-
FutureTask<Integer> futureTask = new FutureTask<Integer>(func);
-
Thread newThread = new Thread(futureTask);
-
newThread.start();
-
-
try {
-
System.out.println("blocking here");
-
Integer result = futureTask.get();
-
System.out.println(result);
-
} catch (InterruptedException ignored) {
-
} catch (ExecutionException ignored) {
-
}
Callable<Integer> func = new Callable<Integer>(){
public Integer call() throws Exception {
System.out.println("inside callable");
Thread.sleep(1000);
return new Integer(8);
}
};
FutureTask<Integer> futureTask = new FutureTask<Integer>(func);
Thread newThread = new Thread(futureTask);
newThread.start();
try {
System.out.println("blocking here");
Integer result = futureTask.get();
System.out.println(result);
} catch (InterruptedException ignored) {
} catch (ExecutionException ignored) {
}
ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。
例子:并行计算数组的和。
Java代码 

-
package executorservice;
-
-
import java.util.ArrayList;
-
import java.util.List;
-
import java.util.concurrent.Callable;
-
import java.util.concurrent.ExecutionException;
-
import java.util.concurrent.ExecutorService;
-
import java.util.concurrent.Executors;
-
import java.util.concurrent.Future;
-
import java.util.concurrent.FutureTask;
-
-
public class ConcurrentCalculator {
-
-
private ExecutorService exec;
-
private int cpuCoreNumber;
-
private List<Future<Long>> tasks = new ArrayList<Future<Long>>();
-
-
-
class SumCalculator implements Callable<Long> {
-
private int[] numbers;
-
private int start;
-
private int end;
-
-
public SumCalculator(final int[] numbers, int start, int end) {
-
this.numbers = numbers;
-
this.start = start;
-
this.end = end;
-
}
-
-
public Long call() throws Exception {
-
Long sum = 0l;
-
for (int i = start; i < end; i++) {
-
sum += numbers[i];
-
}
-
return sum;
-
}
-
}
-
-
public ConcurrentCalculator() {
-
cpuCoreNumber = Runtime.getRuntime().availableProcessors();
-
exec = Executors.newFixedThreadPool(cpuCoreNumber);
-
}
-
-
public Long sum(final int[] numbers) {
-
-
for (int i = 0; i < cpuCoreNumber; i++) {
-
int increment = numbers.length / cpuCoreNumber + 1;
-
int start = increment * i;
-
int end = increment * i + increment;
-
if (end > numbers.length)
-
end = numbers.length;
-
SumCalculator subCalc = new SumCalculator(numbers, start, end);
-
FutureTask<Long> task = new FutureTask<Long>(subCalc);
-
tasks.add(task);
-
if (!exec.isShutdown()) {
-
exec.submit(task);
-
}
-
}
-
return getResult();
-
}
-
-
-
-
-
-
-
public Long getResult() {
-
Long result = 0l;
-
for (Future<Long> task : tasks) {
-
try {
-
-
Long subSum = task.get();
-
result += subSum;
-
} catch (InterruptedException e) {
-
e.printStackTrace();
-
} catch (ExecutionException e) {
-
e.printStackTrace();
-
}
-
}
-
return result;
-
}
-
-
public void close() {
-
exec.shutdown();
-
}
-
}
package executorservice;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
public class ConcurrentCalculator {
private ExecutorService exec;
private int cpuCoreNumber;
private List<Future<Long>> tasks = new ArrayList<Future<Long>>();
// 内部类
class SumCalculator implements Callable<Long> {
private int[] numbers;
private int start;
private int end;
public SumCalculator(final int[] numbers, int start, int end) {
this.numbers = numbers;
this.start = start;
this.end = end;
}
public Long call() throws Exception {
Long sum = 0l;
for (int i = start; i < end; i++) {
sum += numbers[i];
}
return sum;
}
}
public ConcurrentCalculator() {
cpuCoreNumber = Runtime.getRuntime().availableProcessors();
exec = Executors.newFixedThreadPool(cpuCoreNumber);
}
public Long sum(final int[] numbers) {
// 根据CPU核心个数拆分任务,创建FutureTask并提交到Executor
for (int i = 0; i < cpuCoreNumber; i++) {
int increment = numbers.length / cpuCoreNumber + 1;
int start = increment * i;
int end = increment * i + increment;
if (end > numbers.length)
end = numbers.length;
SumCalculator subCalc = new SumCalculator(numbers, start, end);
FutureTask<Long> task = new FutureTask<Long>(subCalc);
tasks.add(task);
if (!exec.isShutdown()) {
exec.submit(task);
}
}
return getResult();
}
/**
* 迭代每个只任务,获得部分和,相加返回
*
* @return
*/
public Long getResult() {
Long result = 0l;
for (Future<Long> task : tasks) {
try {
// 如果计算未完成则阻塞
Long subSum = task.get();
result += subSum;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return result;
}
public void close() {
exec.shutdown();
}
}
Main
Java代码 

-
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 10, 11 };
-
ConcurrentCalculator calc = new ConcurrentCalculator();
-
Long sum = calc.sum(numbers);
-
System.out.println(sum);
-
calc.close();
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 10, 11 };
ConcurrentCalculator calc = new ConcurrentCalculator();
Long sum = calc.sum(numbers);
System.out.println(sum);
calc.close();
四、CompletionService
在刚在的例子中,getResult()方法的实现过程中,迭代了FutureTask的数组,如果任务还没有完成则当前线程会阻塞,如果我们希望任意字任务完成后就把其结果加到result中,而不用依次等待每个任务完成,可以使CompletionService。生产者submit()执行的任务。使用者take()已完成的任务,并按照完成这些任务的顺序处理它们的结果 。也就是调用CompletionService的take方法是,会返回按完成顺序放回任务的结果,CompletionService内部维护了一个阻塞队列BlockingQueue,如果没有任务完成,take()方法也会阻塞。修改刚才的例子使用CompletionService:
Java代码 

-
public class ConcurrentCalculator2 {
-
-
private ExecutorService exec;
-
private CompletionService<Long> completionService;
-
-
-
private int cpuCoreNumber;
-
-
-
class SumCalculator implements Callable<Long> {
-
......
-
}
-
-
public ConcurrentCalculator2() {
-
cpuCoreNumber = Runtime.getRuntime().availableProcessors();
-
exec = Executors.newFixedThreadPool(cpuCoreNumber);
-
completionService = new ExecutorCompletionService<Long>(exec);
-
-
-
}
-
-
public Long sum(final int[] numbers) {
-
-
for (int i = 0; i < cpuCoreNumber; i++) {
-
int increment = numbers.length / cpuCoreNumber + 1;
-
int start = increment * i;
-
int end = increment * i + increment;
-
if (end > numbers.length)
-
end = numbers.length;
-
SumCalculator subCalc = new SumCalculator(numbers, start, end);
-
if (!exec.isShutdown()) {
-
completionService.submit(subCalc);
-
-
-
}
-
-
}
-
return getResult();
-
}
-
-
-
-
-
-
-
public Long getResult() {
-
Long result = 0l;
-
for (int i = 0; i < cpuCoreNumber; i++) {
-
try {
-
Long subSum = completionService.take().get();
-
result += subSum;
-
} catch (InterruptedException e) {
-
e.printStackTrace();
-
} catch (ExecutionException e) {
-
e.printStackTrace();
-
}
-
}
-
return result;
-
}
-
-
public void close() {
-
exec.shutdown();
-
}
-
}
public class ConcurrentCalculator2 {
private ExecutorService exec;
private CompletionService<Long> completionService;
private int cpuCoreNumber;
// 内部类
class SumCalculator implements Callable<Long> {
......
}
public ConcurrentCalculator2() {
cpuCoreNumber = Runtime.getRuntime().availableProcessors();
exec = Executors.newFixedThreadPool(cpuCoreNumber);
completionService = new ExecutorCompletionService<Long>(exec);
}
public Long sum(final int[] numbers) {
// 根据CPU核心个数拆分任务,创建FutureTask并提交到Executor
for (int i = 0; i < cpuCoreNumber; i++) {
int increment = numbers.length / cpuCoreNumber + 1;
int start = increment * i;
int end = increment * i + increment;
if (end > numbers.length)
end = numbers.length;
SumCalculator subCalc = new SumCalculator(numbers, start, end);
if (!exec.isShutdown()) {
completionService.submit(subCalc);
}
}
return getResult();
}
/**
* 迭代每个只任务,获得部分和,相加返回
*
* @return
*/
public Long getResult() {
Long result = 0l;
for (int i = 0; i < cpuCoreNumber; i++) {
try {
Long subSum = completionService.take().get();
result += subSum;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return result;
}
public void close() {
exec.shutdown();
}
}
五、例子HtmlRender
该例子模拟浏览器的Html呈现过程,先呈现文本,再异步下载图片,下载完毕每个图片即显示,见附件eclipse项目htmlreander包。
所有代码见附件,Eclipse项目。本文参考《Java并发编程实践 》。