在学习Java的道路上,是否路过多线程时总让你很迷惘;很不巧,我也是,而使我们感到很迷惘主要原因都源于没有对概念的深深的理解和实践。所以我决定漫步Java多线程,同你一起会会多线程。
多线程系列
多线程系列一:理解多线程在于深深地理解了多任务、进程、多线程、线程
多线程系列二:手撕多线程,从会三种创建多线程方式开始:除了常见的两种,你是否了解Callable接口方式?
多线程系列三:初遇并发问题:从一个小故事开始,从一行行代码开始**
多线程系列四:停止多线程,你不会还以为是用stop和destroy吧?
多线程系列五:多线程为何要使用休眠?
多线程系列六:线程礼让与强制执行
多线程系列七:纯手绘图解多线程状态+代码示例,就问你怕了吗?
一、什么是多任务、进程、多线程、线程?
理解多线程在于深深地理解了多任务、进程、多线程、线程
二、多线程的三种创建方式
创建线程方式一: 继承Thread
继承Thread,重写run()方法,调用strap启动线程。
普通调用方式:调用 run() 方法
代码是自上而下执行的,所以run方法里在主方法前所以结果自然是先run方法后主方法。
如果run方法在主方法后那么自然先主方法后run方法。
普通方法的调用执行顺序是代码的自上而下的顺序。
public class Thread1 extends Thread{
@Override
public void run() {
for (int i = 0;i<=300;i++){
System.out.println("一颗剽悍的种子正在写文章");
}
}
public static void main(String[] args) {
Thread1 t = new Thread1();
t.run(); //调用普通方法
for (int i = 0;i<=300;i++){
System.out.println("一颗剽悍的种子正在听歌");
}
}
}
运行结果
多线程调用方式:调用 start() 方法。
不像普通方法,代码自上而下顺序执行,多线程是调用start是快速的交替执行,所以你才会看到下面的执行结果也是交替的输出。
Thread开启线程方式:
new Thread1().start(); //启动线程
public class Thread1 extends Thread{
@Override
public void run() {
for (int i = 0;i<=300;i++){
System.out.println("一颗剽悍的种子正在写文章"+i);
}
}
public static void main(String[] args) {
new Thread1().start(); //启动线程
for (int i = 0;i<=300;i++){
System.out.println("一颗剽悍的种子正在听歌"+i);
}
}
}
在这里插入图片描述
Runnable接口
继承 Runable 同样需要重写run方法,然后创建 Thread 对象执行start() 方法开启多线程。
Runnable开启线程方式:
new Thread(new Runnable2()).start();
public class Runnable2 implements Runnable{
@Override
public void run() {
for (int i = 0;i<1000;i++){
System.out.println("关注一波一颗剽悍的种子"+i);
}
}
public static void main(String[] args) {
new Thread(new Runnable2()).start();
for (int i = 0;i<1000;i++){
System.out.println("点赞一波一颗剽悍的种子"+i);
}
}
}
三、Thread & Runnable 建议
不建议使用继承Thread类,避免OOP单继承的局限性。
建议使用实现Runnable接口方式,Runnable因为是接口的方式,更加灵活,可以避免单继承的局限性,方便同一个对象被多个线程使用。
但是不管是只使用Thread或Runnable,这两种方式都需要掌握滴。
Callable接口
不同于Thread和Runable需要重写run方法,Callable需要重写的是call
除此之外,Callable比Thread实现起来更加多步骤和复杂
现在Callable作为了解即可,后续我会更进的,放心(前提是有没有关注我呀,嘿嘿)
现在只要知道比起Runnable,Callable重写的 call() 有返回值,而run() 是没有的,并且 call() 可以抛出受检查的异常。
1. 首先实现Callable接口。 |
---|
2. 重写call并抛出异常。 |
3.创建目标对象。 |
4.创建执行服务。 |
5.提交执行。 |
6.获取结果。 |
7.关闭服务。 |
public class Callable3 implements Callable<Object>{
@Override
public Object call() throws Exception {
System.out.println(Thread.currentThread().getName());
return null;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable3 t1 =new Callable3();
Callable3 t2 =new Callable3();
Callable3 t3 =new Callable3();
//创建执行服务:
ExecutorService service = Executors.newFixedThreadPool(6);
//提交执行
Future<Object> r1 = service.submit(t1);
Future<Object> r2 = service.submit(t2);
Future<Object> r3 = service.submit(t3);
//获取结果
r1.get();
r2.get();
r3.get();
System.out.println(r1);
System.out.println(r2);
System.out.println(r3);
//关闭服务
service.shutdownNow();
}
}
为了更好的阅读体验,我把想说的话都放在了下面,嘿嘿。
我是一颗剽悍的种子 把我会的,认真的分享 是我写博客一直不变的信条。
如果你能看到这篇博文,说明咱们还是很有缘的;希望能带给你一些许帮助,创作的不易, 把我文章的知识带走,你的三连留下,点赞,评论,关注,是我最大的动力。
谢谢你这么可爱,还关注我~