Runnable和Callable的区别是,
(1)Callable规定的方法是call(),Runnable规定的方法是run().
(2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值得
(3)call方法可以抛出异常,run方法不可以
(4)运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
1.1使用Runnble接口 创建线程
public class RunnableTest implements Runnable {
@Override
public void run() {
System.out.println("this thread name is:"+Thread.currentThread().getName());
}
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
RunnableTest r = new RunnableTest();
Thread t = new Thread(r);
t.start();
}
}
或者使用匿名类实现:
Thread thread =new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
System.out.println("匿名类实现线程");
}
使用1.2 使用 Executors 创建线程
package com.asiainfo.proxydemo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadExecutorService {
//设置线程的数量
private static int POOL_NUM=10;
/**
* @param args
*/
public static void main(String[] args) {
// ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3);
// ExecutorService newFixedThreadPool = Executors.newCachedThreadPool();
// ExecutorService newFixedThreadPool = Executors.newScheduledThreadPool(3);
// ExecutorService newFixedThreadPool = Executors.newSingleThreadExecutor();
ExecutorService newFixedThreadPool = Executors.newSingleThreadScheduledExecutor();
for (int i = 0; i < POOL_NUM; i++) {
RunnableImpl runnableImpl = new RunnableImpl("thread--"+i);
newFixedThreadPool.execute(runnableImpl);
}
newFixedThreadPool.shutdown();
}
}
class RunnableImpl implements Runnable{
private String name;
public RunnableImpl(String name) {
super();
// TODO Auto-generated constructor stub
this.name=name;
}
public void run() {
// TODO Auto-generated method stub
System.out.println("hello ExecutorService"+name);
}
}
2.1 使用Callable 创建线程
package com.asiainfo.proxydemo;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class ThreadCallable {
/**
* @param args
*/
public static void main(String[] args) {
Tickets<java.lang.Object> tickets = new Tickets<Object>();
FutureTask<java.lang.Object> futureTask = new FutureTask<Object>(tickets);
Thread thread = new Thread(futureTask);
System.out.println(Thread.currentThread().getName());
thread.start();
}
}
class Tickets<Object> implements Callable<Object>{
/* (non-Javadoc)
* @see java.util.concurrent.Callable#call()
*/
public Object call() throws Exception {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName()+"通过实现Callable接口通过FutureTask包装器来实现线程");
return null;
}
}
2.2 使用 Executors 结合Callable 创建多线程
在Java5之 后,任务分两类:一类是实现了Runnable接口的类,一类是实现了Callable接口的类。两者都可以被ExecutorService执行,但是 Runnable任务没有返回值,而Callable任务有返回值。并且Callable的call()方法只能通过ExecutorService的 submit(Callable<T> task) 方法来执行,并且返回一个 <T> Future<T>,是表示任务等待完成的 Future.
public interface Callable<V>返回结果并且可能抛出异常的任务。实现者定义了一个不带任何参数的叫做 call 的方法。
Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。
Executors 类包含一些从其他普通形式转换成 Callable 类的实用方法。
Callable中的call()方法类似Runnable的run()方法,就是前者有返回值,后者没有。
当将一个Callable的对象传递给ExecutorService的submit方法,则该call方法自动在一个线程上执行,并且会返回执行结果Future对象。
同样,将Runnable的对象传递给ExecutorService的submit方法,则该run方法自动在一个线程上执行,并且会返回执行结果Future对象,但是在该Future对象上调用get方法,将返回null.
package com.asiainfo.proxydemo;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class ThreadCallableDemo2 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<String>> resultList = new ArrayList<Future<String>>();
// 创建10个任务并执行
for (int i = 0; i < 10; i++) {
// 使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
Future<String> future = executorService.submit(new TaskWithResult(i));
// 将任务执行结果存储到List中
resultList.add(future);
}
// 遍历任务的结果
for (Future<String> fs : resultList) {
try {
System.out.println(fs.get()); // 打印各个线程(任务)执行的结果
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
// 启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用。
executorService.shutdown();
}
}
}
}
class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) {
this.id = id;
}
public String call() throws Exception {
System.out.println("call()方法被自动调用,干活!!! " + Thread.currentThread().getName());
// 一个模拟耗时的操作
for (int i = 999999; i > 0; i--)
;
return "call()方法被自动调用,任务的结果是:" + id + " " + Thread.currentThread().getName();
}
}
参考:https://blog.csdn.net/w2393040183/article/details/52177572
http://murielily.blog.163.com/blog/static/134260649201131215237637/