最近在学习java多线程,在这里记录一下实现多线程的方式:
1.继承Tread类,重写run方法:
public class TheadTest01 {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
// 使用start方法开启线程
new MyThread(i).start();
}
}
}
// 继承Thread类
class MyThread extends Thread {
private int i;
public MyThread(int i) {
this.i = i;
}
// 重写run方法
@Override
public void run() {
System.out.print(i + " ");
}
}
2.实现Runnable接口,重写run方法:
public class RunnableTest01 {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Runnable ra = new MyRunnable(i);
// 通过Thread的构造函数传入参数,使用start方法开启线程
new Thread(ra).start();
}
}
}
// 实现Runnable接口
class MyRunnable implements Runnable {
private int i;
public MyRunnable(int i) {
this.i = i;
}
// 实现run方法
@Override
public void run() {
System.out.println(i);
}
}
这里需要将Runnable对象当做参数通过构造函数传入创建的Thread对象中,这里简单看一下Thread类的源码:
public class Thread implements Runnable
首先可以看到Thread类也实现了Runnable接口,再看一下Thread的run方法:
@Override
public void run() {
if (target != null) {
target.run();
}
}
可以发现,Thread类的run方法只是运行传入Runnable对象的run方法,自身没有做过多实现。
3.实现Callable接口,重写call方法:
public class CallableTest01 {
public static void main(String[] args) throws Exception {
for (int i = 0; i < 10; i++) {
// 创建Callable对象
Callable<Integer> ca = new MyCallable(i);
// 创建FutureTask对象,并通过构造函数将Callable对象传入
FutureTask<Integer> future = new FutureTask<Integer>(ca);
// 创建Thread对象,将FutureTask对象当做参数传入,通过start方法启动线程
// Runnable ra = future;
// new Thread(ra).start();
new Thread(future).start();
}
}
}
// 实现Callable接口
class MyCallable implements Callable<Integer> {
private int i;
public MyCallable(int i) {
this.i = i;
}
// 重写call方法
@Override
public Integer call() throws Exception {
System.out.println(i);
return i;
}
}
可以发现,使用Callable接口实现多线程,需要将Callable对象通过构造函数传入创建的FutureTask对象中,然后将FutureTask对象通过构造函数传入Thread对象中,才能运行。通过观察Thread的构造函数发现并不能接受FutureTask类型的参数,为什么还能传入呢?这是因为FutureTask类实现了Runnable接口:
public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V>
所以Thread类可以接受FutureTask作为构造参数,类似于:
Runnable ra = future;
new Thread(ra).start();
使用Callable接口实现多线程还是可以获取返回值的,使用FutureTask对象的get方法即可,不过如果对每个FutureTask对象直接使用get方法的话,会因为阻塞而不能实现多线程的效果,这时可以通过集合搜集FutureTask对象,然后调用get方法,代码如下:
public static void main(String[] args) throws Exception {
// 创建FutureTask<Integer>集合
List<FutureTask<Integer>> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
// 创建Callable对象
Callable<Integer> ca = new MyCallable(i);
// 创建FutureTask对象,并通过构造函数将Callable对象传入
FutureTask<Integer> future = new FutureTask<Integer>(ca);
// 将FutureTask对象放入集合中
list.add(future);
// 创建Thread对象,将FutureTask对象当做参数传入,通过start方法启动线程
new Thread(future).start();
// 不能实现异步
// System.out.println(future.get());
}
// 使用FutureTask对象的get方法获取返回值
int result = 0;
for (int i = 0, len = list.size(); i < len; i++) {
result += list.get(i).get();
}
System.out.println("
result=" + result);
}