【线程基础】实现多线程
方法一 继承Thread类
public class Thread01 extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" is running...");
}
public static void main(String[] args) {
Thread01 thread01 = new Thread01();
thread01.start();
}
}
方法二 实现Runnable接口
public class Thread02 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" is running...");
}
public static void main(String[] args) {
Thread thread = new Thread(new Thread02());
thread.start();
}
}
方法三 通过Callable和FutureTask创建线程
public class Thread03 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<String> callable = new Callback<String>();
FutureTask<String> futureTask = new FutureTask<>(callable);
Thread thread = new Thread(futureTask);
thread.start();
System.out.println(futureTask.get());
}
static class Callback<String> implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("exec one times...");
TimeUnit.SECONDS.sleep(2);
System.out.println("sleep tow seconds");
return (String) (Thread.currentThread().getName() + " is pass through callable accomplish");
}
}
}
方法四 通过线程池创建线程
public class Thread04 {
static class RunnableTask implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" is running...");
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.execute(new RunnableTask());
executorService.shutdown();
}
}
方法五 定时器Timer
public class Thread05 extends TimerTask {
@Override
public void run() {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)+":"+Thread.currentThread().getName()+" is running...");
}
public static void main(String[] args) {
Timer timer = new Timer();
//隔一秒后启动,之后每隔两秒启动一次。
timer.schedule(new Thread05(), 1000,2000);
}
}
方法六 匿名内部类创建线程
public class Thread06 {
public static void main(String[] args) {
Thread thread = new Thread(()->{
System.out.println(Thread.currentThread().getName()+" is running...");
});
thread.start();
}
}
总结
在上面六种方法中虽然都能创建线程,但其实他们每种方法在内部,其实都是通过实现Runnable接口来实现的
可以看到,不管创建线程的方式千遍万化,他的底层始终都逃不过实现Runnable接口,所以归根结底,创建线程的方式只有一种。
单如果仔细想一下,为什么Java都创建线程的方式都做成实现Runnable接口来看,相比继承Thread接口,实现Runnable接口有什么好处。
- 其实在Java中,只允许单继承,但是可以实现多接口。对于这个特性其实就体现出了线程去实现Runnable接口的灵活性。
- 另外,在某些情况下通过实现Runnable的方式可以提高性能。使用继承Thread的方式,没执行一次任务,都需要新建一个独立的线程,执行完任务后的线程周到生命周期的尽头被销毁,如果还想执行这个任务,就必须要再新建一个继承Thread类的线程。如果用实现Runnable接口的方式,就可以直接把任务直接传入线程池,使用一些固定的线程来完成任务,不需要新建和销毁线程。这样就大大的降低了性能开销。
总结一下,如果有面试官问我们一共有几种创建线程的方式,就跟他说只有一种,那就是通过实现Runnable接口的方式来创建线程。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix