学习Java多线程记录
基础部分
创建一个线程
一、继承Thread类
1.定义Thread的子类,并重写run方法,run方法体就是线程要执行的任务。
2.创建Thread子类的实例对象,即创建线程对象。
3.调用线程对象的start()方法来启动线程。
public class DemoThread extends Thread{
public void run(){
System.out.println("hello");
}
public static void main(String[] args){
new DemoThread().start();
}
}
二、实现Runnable
1.定义runnable接口的实现类,并重写run方法,run方法体就是线程要执行的任务。
2.创建Runnable实现类的实例对象,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
3.调用线程对象的start()方法来启动线程。
public class Demo implements Runnable{
public void run(){
System.out.println("hello");
}
public static void main(String[] args){
Demo de = new Demo();
new Thread(de,"新线程").start();
}
}
三、实现Callable与Future
1.创建Callable接口的实现类,并实现call()方法作为线程执行体(即run方法内的任务),并有返回值。
2.创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。(FutureTask是一个包装器,它通过接受Callable来创建,同时实现了Future和Runnable接口)
3.使用FutureTask对象作为Thread对象的targe创建并启动新线程。
4.调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
public class Demo implements Callable<Integer> {
public static void main(String[] args) {
Demo de = new Demo();
FutureTask<Integer> ft = new FutureTask<>(de);
new Thread(ft,"有返回值的线程").start();
try {
ft.get();
}catch (Exception ex){
...
}
}
@Override
public Integer call() throws Exception{
return 1;
}
}
常用线程池体系结构
1.Executor:线程池顶级接口
public interface Executor{
/**
*执行无返回值任务
*根据Executor的实现判断,可能时在新线程、线程池、线程调用中执行
*/
void execute(Runnable command);
}
2.ExecutorService:线程池次级接口,对Executor做了一些扩展,增加了一些功能;
public interface ExecutorService extends Executor{
//关闭线程池,不再接受新任务,但已经提交的任务会执行完成
void shutdown();
/**
*立即关闭线程池,尝试停止正在运行的任务,未执行的任务将不再执行
*被迫停止及未执行的任务将以列表的形式返回
*/
List<Runnable> shutdownNow();
//检查线程池是否关闭
boolean isShutdown();
//检查线程池是否已终止,只有在shutdown()或shutdownNow()之后调用才有可能为true
boolean isTerminated();
//在指定时间内线程池达到终止状态才会返回true
boolean awaitTermination(long var1, TimeUnit var3) throws InterruptedException;
//执行有返回值的任务,任务的返回值为task.call()的结果
<T> Future<T> submit(Callable<T> task);
//执行有返回值的任务,任务的返回值为这里传入的var2,只有当任务执行完成了调用get()时才会返回
<T> Future<T> submit(Runnable var1, T var2);
//执行有返回值的任务,任务的返回值为null,只有当任务执行完成了调用get()时才会返回
Future<?> submit(Runnable var1);
//批量执行任务,只有当这些任务都执行完成了这个方法才会返回
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
//在指定时间内批量执行任务,未执行完成的任务将被取消,timeout是所有任务的总时间,不是单个任务的时间
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit var4) throws InterruptedException;
//返回任意一个已完成任务的执行结果,未执行完成的任务将被取消
<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;
//在指定时间内如果有任务已完成,则返回任意一个已完成任务的执行结果,未执行完成的任务将被取消
<T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit var4) throws InterruptedException, ExecutionException, TimeoutException;
}
3.ScheduleExecutorService:对ExecutorService做了一些扩展,增加了一些定时任务相关的功能
4.AbstractExecutorService:抽象类,运用模板方法设计模式实现了一部分方法
5.ThreadPoolExecutor:普通线程池类,包含最基本的一些线程池操作相关的方法实现
6.ScheduledThreadPoolExecutor:定时任务线程池类,用于实现定时任务相关功能
7.ForkJoinPool:新型线程池类,java7中新增的线程池类,基于工作窃取理论实现,运用于大任务拆小任务,任务无限多的场景
8.Excutors:线程池工具类,定义了一些快速实现线程池的方法