作者:封鹏 | 来源:互联网 | 2023-08-18 11:23
学习之前建议先看 2. Java并发编程之 进程和线程,并行和并发
这篇博文科普下Java 创建线程的三种方法以及线程池的几种类型。
1 如何创建线程?
-
- 继承自Thread类 (不推荐)
-
- 实现Runnable接口(无返回值)
-
- 实现Callable接口(有返回值)
1.1 第一种方法:继承Thread 类
步骤:
1.继承自Thread类
2.重写run方法
public class MyThreadOne extends Thread {
@Override
public void run() {
super.run();
//我们可以通过调用 Thread.currentThread().getName(); 获取当前线程名称
System.out.println("当前线程名称:"+Thread.currentThread().getName()+":Do Somthing");
}
}
调用方式
public class MyThreadOneTest {
public static void main(String[] args) {
//创建一个继承自Thread类的实例对象
MyThreadOne myThreadOne=new MyThreadOne();
//创建一个线程使用默认的线程名称thread-1
//Thread myThread=new Thread(myThreadOne);
//创建一个线程并指定线程名称
Thread myThread=new Thread(myThreadOne,"My Thread One");
//启动线程
myThread.start();
}
}
打印结果:
当前线程名称:My Thread One:Do Somthing
这种方式弊端很明显,因为一旦我们当前类已经继承了其他类作为父类,那么就没有办法再继承Thread类了(Java中类是单继承的),因此这种方式几乎不会使用。
有没有更好的方法呢? 有,那就是接下来讲的第二种方法。
1.2 第二种方法:实现Runable接口
我们知道Java之中虽然类不可以多继承,但是接口却可以多继承,并且一个类可以实现多个接口。
步骤:
1.实现Runnbale接口
2.重写run方法
public class MyThreadTwo implements Runnable {
@Override
public void run() {
//我们可以通过调用 Thread.currentThread().getName(); 获取当前线程名称
System.out.println("当前线程名称:"+Thread.currentThread().getName()+":Do Somthing");
}
}
调用方法如下
public class MyThreadTwoTest {
public static void main(String[] args) {
//创建一个实现Runnable接口类的实例对象
MyThreadTwo myThreadTwo=new MyThreadTwo();
//创建一个线程使用默认的线程名称thread-1
//Thread myThread=new Thread(myThreadTwo);
//创建一个线程并指定线程名称
Thread myThread=new Thread(myThreadTwo,"My Thread Two");
//启动线程
myThread.start();
}
}
执行结果如下:
当前线程名称:My Thread Two:Do Somthing
1.3 第三种方法:实现Callable 接口
第二种方法比第一种方法得到了优化,但是仍然有一个问题,假如我们想要线程结束后需要有返回值,那么该怎么做呢?
步骤一:
- 实现Callable接口
- 重写接口的call()方法
V是泛型,可以是String,也可以是任意Object对象
public class MyThreadThree implements Callable {
@Override
public String call() throws Exception {
//我们可以通过调用 Thread.currentThread().getName(); 获取当前线程名称
System.out.println("当前线程名称:"+Thread.currentThread().getName()+":Do Somthing");
return "thread three result";
}
}
3.调用如下:
这里我们注意到和之前有些改动。
- 1.我们不能再使用Thread类直接包装我们的自定义类
- 2.需要
new FutureTask<>(myThreadThree)
包装我们的自定义类
FutureTask futureTask&#61;new FutureTask<>(myThreadThree);
- 3.然后使用Thread类包装下
FutureTask
Thread myThread&#61;new Thread(futureTask,"My Thread Three");
- 4.futureTask.get() 获取线程返回的结果
代码如下&#xff1a;
public class MyThreadThreeTest {
public static void main(String[] args) {
//创建一个实现Callable接口类的实例对象
MyThreadThree myThreadThree&#61;new MyThreadThree();
//V 是泛型&#xff0c;可以是String 也可以是任意Object类型
//FutureTask 中的V要和 Callable V类型保持一致
//使用FutureTask对象来包装实现Callable接口类的实例对象
FutureTask futureTask&#61;new FutureTask<>(myThreadThree);
//创建一个线程使用默认的线程名称thread-1
//Thread myThread&#61;new Thread(futureTask);
//创建一个线程并指定线程名称
Thread myThread&#61;new Thread(futureTask,"My Thread Three");
//启动线程
myThread.start();
try {
//获取线程返回的结果
String result&#61; futureTask.get();
//打印线程返回的结果
System.out.println(result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
执行结果&#xff1a;
当前线程名称:My Thread Three:Do Somthing
thread three result
参考文献&#xff1a;
《Java并发编程的艺术》
《Java编程思想》
《码出高效Java开发手册》
本节完~
没看够&#xff0c;继续看 4. Java并发编程之使用线程池管理线程