Java Thread 创建的三种方式
概述
Java为单进程多线程的模式,在处理并发时常常使用多个线程来处理,在Tomcat
druid
等中间件中都有线程的应用。
线程是进程的执行单元,线程依靠进行执行,只能使用进程分配的资源;在Java中每个线程都有单独的程序计数器、栈空间,相对于进程开销较小,线程是cpu调试的最小单元。
线程可分为主线程
子线程
后台线程
,主线程由JVM启动,并调用main
方法,子线程由用户开启,后台线程为了线程的一种。后台线程不能单独开启,当JVM中只有后台线程时会退出。创建线程有三种方法。
亲娘Thread
Thread
代表了线程;可以直接使用子类继承Thread
类的方法创建一个新的子线程。
public void demo(){
//创建线程实例
MyThread thread=new MyThread();
//调用start方法启动线程
thread.start();
}
//定义子类
public class MyThread extends Thread{
//重写run方法
@Override
public void run() {
super.run();
}
}
亲娘Thread生出了MyThead;MyThread得到了Thread的所有原生关爱。
二娘Runnable
Runnable
实际并没有创建线程;Runnable
实则是一个接口且只有一个run
方法,这个接口可以使用lambda
表示也可以实现一个子类继承自Runnable
接口,最后将实例交给Thread
执行。
public void demo(){
//使用lambda表达式表示入口并创建一个线程
new Thread(()->{
System.out.println("Runnable");
})
//启动线程
.start();
}
二娘Runnable
实则还是交给了Thread
去关爱。
三娘FutureTask
Callable
可比Runnable
要争气点;可以获取到执行的结果;但还需要和Future
配合使用;Future
可以取消正在执行的任务。
public interface Future<V> {
//取消
boolean cancel(boolean mayInterruptIfRunning);
//是否已经取消
boolean isCancelled();
//是否完成
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
虽然Callable
比Runnable
要争气,两兄弟还是要看Thread
的脸色,所以两兄弟也比较团结会取长补短。
FutureTask
会护着这两兄弟,创建一个FutureTask
可以使用Callable
Runnable
做为入参,再提交到ExecutorService
线程池中进行调度,当然也可以交给Thread
进行调度;因为它实现了Runnable
接口和它关系也不错。
public void demo() throws ExecutionException, InterruptedException {
//使用Callable创建FutureTask
FutureTask<Boolean> task = new FutureTask<>(() -> {
System.out.println("Callable");
return true;
});
//创建线程池
ExecutorService executorService = Executors.newCachedThreadPool();
//托管给线程池调度
Future<?> future = executorService.submit(task);
//获取结果
Object o = future.get();
//用Thread调试FutureTask
new Thread(task)
.start();
}
精彩推荐:
Java ClassLoader详解双亲委派的实现原理
Java 反射技术应用与详解
Java 8种基本值类型