孔乙己蘸着酒,在桌上了写下五种创建线程的方法。
1. 继承自Thread类
- 不足:java只允许单继承,一旦继承了Thread类就无法再继承其他类了。
public class ExThreads extends Thread {
@Override
public void run() {
System.out.println("我是t1线程");
}
public static void main(String[] args) {
Thread t1 = new ExThreads();
t1.start();
}
}
2. 实现Runnable接口
Thread类的构造方法允许传入一个对象,该对象必须实现Runnable接口。
这其实是一个典型的设计模式:静态代理。Thread类在执行的时候,实际上调用的就是这个对象的run方法。
这让我想起一部电影《师父》,咏春拳要在天津开武馆,需要收一个天津本地人为弟子,让他代替师父去踢馆。
public class ImpRunnable implements Runnable{
@Override
public void run() {
System.out.println("我是t1线程");
}
public static void main(String[] args) {
Thread t1 = new Thread(new ImpRunnable());
t1.start();
}
}
3. 实现Runnable接口(二)
借助于lambda表达式,简化。
public class ImpRunnable2 {
public static void main(String[] args) {
Thread t1 = new Thread(()->{
System.out.println("我是t1线程");
});
t1.start();
}
}
4. 实现Callable接口
由于java线程运行是void类型,没有返回值。后来增加了Callable接口,可以返回一个泛型返回值。
public class FutureCallableThread implements Callable<String> {
@Override
public String call() throws Exception {
return LocalDateTime.now().toString();
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<String> future = executorService.submit(new FutureCallableThread());
//此时使用线程池提交任务后,future.get()方法是阻塞的,会等待call()完成返回。
String str = future.get();
System.out.println(str);
executorService.shutdown();
}
}
5. 实现Callable接口(二)
FutureTask实现了Runnable接口,因此用他能构建线程类。同时,他也继承了Future接口,可以返回future。
public class FutureTaskThread implements Callable<String> {
@Override
public String call() throws Exception {
return LocalDateTime.now().toString();
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
//先包住一层
FutureTask<String> task = new FutureTask(new FutureCallableThread());
//再包住一层
Thread t1 = new Thread(task);
t1.start();
System.out.println(task.get());
}
}
6. 借助于线程池
其本质还是和前面几种是一样的。
public class UsingExecutors {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("我是t1线程");
}
});
executorService.shutdown();
}
}
总结
线程创建方式很多,其核心还是Runnable接口和Thread类。
多线程系列在github上有一个开源项目,主要是本系列博客的实验代码。
https://github.com/forestnlp/concurrentlab
如果您对软件开发、机器学习、深度学习有兴趣请关注本博客,将持续推出Java、软件架构、深度学习相关专栏。
您的支持是对我最大的鼓励。
本文详细介绍了Java中创建线程的六种方法,包括继承Thread类、实现Runnable接口、利用lambda简化、实现Callable接口获取返回值以及使用线程池。通过实例代码展示了每种方法的使用,并强调了线程池的重要性。最后,文章提供了开源项目链接以供进一步学习。
1383

被折叠的 条评论
为什么被折叠?



