1.Thread类和Runable接口
JDK提供了Thread和Runanle接让我们实现自己的线程类。
- 继承Thread类,重写run()方法;
- 实现Runable接口,实现run()方法
2.Thread常用的几个方法
currentThread():静态方法,返回对当前正在进行线程的引用;
start():开始调用线程的方法,java虚拟机会调用run()方法;
yield():当前线程愿意让出对当前处理器的占用;
sleep();使当前线程睡眠一段时间;
join():使当前线程等待另一个线程执行瓦尼比之后再执行,内部调用的是Object的wait()方法。
3.Thread类与Runable接口的比较
(1)java“单继承,多实现”的特性,Runable比Thread更灵活。
(2)Runable接口更符合面向对象,将县城进行单独封装;
(3)Runable接口降低了线程对象和线程任务的耦合性;
(4)使用线城时不需要Thread类的诸多方法,Runable接口更轻量级一些。
总结:优先使用Runable接口实现线程类。
4.Callable接口、Future接口与FutureTask类
使用Thread类和Runable创建的线程,执行的run()方法没有返回值。
JDK提供了Callable接口和Future接口为我们解决这个问题,这也是所谓的“异步”模型。
4.1Callable接口
Callable接口配合线程池工具ExecutorService使用,ExecuttorService调用submit()方法让callable线程执行,返货一个Future,通过Future的get得到这个返回值。
eg:
public static class MyThread implements Callable {
@Override
public Integer call() throws Exception {
System.out.println("进入了callable-----------");
return 222;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService=Executors.newCachedThreadPool();
MyThread thread=new MyThread();
Future<Integer> result= executorService.submit(thread);
System.out.println(result.get());}
4.2 Future接口
future接口的全部方法
public abstract interface Future<V> {
public abstract boolean cancel(boolean paramBoolean);
public abstract boolean isCancelled();
public abstract boolean isDone();
public abstract V get() throws InterruptedException, ExecutionException;
public abstract V get(long paramLong, TimeUnit paramTimeUnit)
throws InterruptedException, ExecutionException, TimeoutException;
}
paramBoolean参数表示是否采取中断的方式取消执行。
cancel()方法是试图取消一个线程的执行。
如果为了让任务又能够取消的功能,就用callable代替runable.
入股哦为了任务有可取消性,但不需要返回结果,则可声明Feture<?>形式类型,返回null作为底层任务的结果。
public static class MyThread implements Callable {
@Override
public Future<?> call() throws Exception {
System.out.println("进入了callable-----------");
return null;
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
MyThread thread = new MyThread();
Future<Integer> result = executorService.submit(thread);
result.cancel(false);
}
4.3 FutureTask类
FutureTask接口实现了RunableFuture接口,
RunableFuture同时继承了Runbale接口和Future接口。
FutureTask类的作用,实现了Future接口的方法直接共我饿们使用。
public static class MyThread implements Callable {
@Override
public Integer call() throws Exception {
System.out.println("进入了callable-----------");
return 111;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
FutureTask<Integer> futureTask = new FutureTask<>(new MyThread());
executorService.submit(futureTask);
System.out.println(futureTask.get());
}
4.3FutureTask执行多任务计算的使用场景
利用FutureTask 和ExectutorService,可以用多线程的方式提交计算任务,主线程继续执行其他任务,当主线程需要子线程的计算结果时,在异步获取子线程的执行结果。
public static class MyThread implements Callable<Integer> {
private Integer result = 0;
private String taskName = "";
public MyThread(Integer initResult, String taskName) {
result = initResult;
this.taskName = taskName;
System.out.println("生成子线程计算任务:" + taskName);
}
@Override
public Integer call() throws Exception {
for (int i = 0; i < 100; i++) {
result = +i;
}
//休眠5秒
Thread.sleep(5000);
System.out.println("子线程计算任务:" + taskName + "执行完成");
return result;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
Main initMain = new Main();
//创建任务集合
List<FutureTask<Integer>> taskList = new ArrayList<>();
//创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
//传入callable对象,创建FutureTask任务
FutureTask<Integer> ft = new FutureTask<Integer>(new MyThread(i, "" + i));
taskList.add(ft);
//提交给线程池任务
executorService.submit(ft);
}
System.out.println("所有计算任务提交完毕");
//统计线程计算结果
Integer totalResult = 0;
for (FutureTask<Integer> task : taskList) {
totalResult = totalResult + task.get();
}
executorService.shutdown();
System.out.println("多任务的计算结果为:" + totalResult);
}
4.4 FutureTask在高并发下确保任务只执行一次
用ConcurrentHash,可以避免加锁的情况。此例子避免了鱿鱼板并发带来的重复创建及锁的出现。
public class Main extends Thread {
private Map<String, FutureTask<Integer>> taskPool = new ConcurrentHashMap<String, FutureTask<Integer>>();
public Integer getTask(String key) throws ExecutionException, InterruptedException {
FutureTask<Integer> task = taskPool.get(key);
System.out.println("task=:"+task);
if (task != null) {
return task.get();
} else {
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return creatKey();
}
};
FutureTask<Integer> newTask = new FutureTask<Integer>(callable);
task = taskPool.putIfAbsent(key, newTask);
if (task == null) {
task = newTask;
task.run();
}
}
return task.get();
}
private Integer creatKey() {
return 122;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
Main main = new Main();
System.out.println("result=:" + main.getTask("qww"));
}