常见的Java线程的4中方式包括:继承Thread类、实现Runnable接口、通过ExcutorService和Callable实现有返回值的线程、基于线程池创建。
继承Thread类
步骤:
- 定义一个Thread类的子类,重写run方法,将相关逻辑实现,run()方法就是线程要执行的业务逻辑方法
- 创建自定义的线程子类对象
- 调用子类实例的star()方法来启动线程
public class MyExtendThread extends Thread {
@Override
public void run() {
//super.run();
System.out.println(Thread.currentThread().getName() + " run()方法正在执行...");
}
public static void main(String[] args) {
MyExtendThread myExtendThread = new MyExtendThread();
myExtendThread.start();
System.out.println(Thread.currentThread().getName() + " main()方法执行结束");
}
}
main main()方法执行结束
Thread-0 run()方法正在执行…
实现Runnable接口
步骤
- 定义Runnable接口实现类MyRunnable,并重写run()方法
- 创建MyImplRunnable 实例MyImplRunnable ,以MyImplRunnable 作为target创建Thead对象,该Thread对象才是真正的线程对象
- 调用线程对象的start()方法
public class MyImplRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " Runnable run()方法正在执行...");
}
public static void main(String[] args) {
MyImplRunnable myImplRunnable = new MyImplRunnable();
Thread thread = new Thread(myImplRunnable);
thread.start();
System.out.println(Thread.currentThread().getName() + " main()方法执行结束");
}
}
main main()方法执行结束
Thread-0 Runnable run()方法正在执行…
使用Callable和Future创建有返回值的线程
步骤
- 创建实现Callable接口的类MyImplCallable
- 以MyImplCallable 为参数创建FutureTask对象
- 将FutureTask作为参数创建Thread对象
- 调用线程对象的start()方法
public class MyImplCallable implements Callable<String> {
String name=null;
public MyImplCallable() {
}
public MyImplCallable(String name) {
this.name = name;
}
@Override
public String call() throws Exception {
//"带有返回值的线程创建方式");
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + " call()方法正在执行...");
return Thread.currentThread().getName()+" SUC "+name;
}
public static void main(String[] args) {
FutureTask<String> futureTask = new FutureTask<String>(new MyImplCallable());
Thread thread = new Thread(futureTask);
thread.start();
try {
Thread.sleep(1000);
try {
System.out.println("线程返回值"+futureTask.get());
} catch (ExecutionException e) {
e.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " main()方法执行结束");
}
}
Thread-0 call()方法正在执行…
线程返回值Thread-0 SUC null
main main()方法执行结束
使用Executor框架创建线程池
Executors提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
主要有newFixedThreadPool,newCachedThreadPool,newSingleThreadExecutor,newScheduledThreadPool。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorServiceCreate {
public static void main(String[] args) {
ExecutorService executorService= Executors.newFixedThreadPool(5);
for(int i=0;i<5;i++){
executorService.execute(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " run()方法正在执行...");
});
}
//关闭线程池,否则服务一直在
executorService.shutdown();
System.out.println(Thread.currentThread().getName() + " main()方法执行结束");
}
}
main main()方法执行结束
pool-1-thread-4 run()方法正在执行…
pool-1-thread-2 run()方法正在执行…
pool-1-thread-3 run()方法正在执行…
pool-1-thread-1 run()方法正在执行…
pool-1-thread-5 run()方法正在执行…
此处要注意阿里开发规范《阿里巴巴Java开发手册(泰山版)》:
4. 【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这
样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors 返回的线程池对象的弊端如下:
1) FixedThreadPool 和 SingleThreadPool:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2) CachedThreadPool:
允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
几个关键类的关系图
Thread类的关键构造函数
实战例子
public class MyThreadPoolByFutureTask {
public static void main(String[] args) {
//Executors.newFixedThreadPool(5);
ExecutorService executorService=
new ThreadPoolExecutor(5, 5,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
List<Future> list = new ArrayList<Future>();
for(int i=0;i<5;i++){
Callable callable= new MyImplCallable(i+" callable");
Future future = executorService.submit(callable);
list.add(future);
}
executorService.shutdown();
for(Future future:list){
try {
System.out.println("线程执行完毕之后查看线程返回值 "+future.get().toString());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
pool-1-thread-4 call()方法正在执行…
pool-1-thread-1 call()方法正在执行…
线程执行完毕之后查看线程返回值 pool-1-thread-1 SUC 0 callable
pool-1-thread-5 call()方法正在执行…
pool-1-thread-2 call()方法正在执行…
pool-1-thread-3 call()方法正在执行…
线程执行完毕之后查看线程返回值 pool-1-thread-2 SUC 1 callable
线程执行完毕之后查看线程返回值 pool-1-thread-3 SUC 2 callable
线程执行完毕之后查看线程返回值 pool-1-thread-4 SUC 3 callable
线程执行完毕之后查看线程返回值 pool-1-thread-5 SUC 4 callable