对于Java多线程的使用,方法有几种
- 直接使用 Thread执行,
- 使用Runnable 配合 Thread 使用:
- FutureTask 配合 Thread 使用,即使使用Callable类型。
方法二中:Tread代表线程,而Runnable代表可执行的任务,就是线程要执行的代码
方法一和方法二的区别:方法一将任务和线程合并在了一起,而方法二是将线程和任务分开
使用方法2,可以更加容易与线程池等高级API配合,让任务类脱离 Thread的继承体现,更加灵活
而方法三的最大区别就是可以返回参数
1. 线程的创建
// 继承Thread类
class Thread1 extends Thread{
@Override
public void run(){
System.out.println("Thread");
}
}
// 实现Rubbable接口
class Thread2 implements Runnable{
@Override
public void run() {
System.out.println("Runnable");
}
}
// 实现Callable接口
class Thread3 implements Callable<Object>{
@Override
public Object call() throws Exception {
return null;
}
}
2. 线程的启动
Thread的启动
// Thread的启动
new Thread1().start();
Runnable的启动
// Runnable的启动
new Thread(new Thread2()).start();
Callable的启动
FutureTask<Object> futureTask = new FutureTask(new Thread3());
new Thread(futureTask).start();
try {
Object object = futureTask.get();
System.out.println(object);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
上述方法启动后的输出结果如下
Thread
Runnable
Callable
null
3.区别
上面一共使用了三种方法,分别是Thread,Runnable和Callable。三者之间的区别我们从源码来看
// Thread的源码开头
public
class Thread implements Runnable {
...
}
// Runnable的源码
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
由源码知道,Thread也是使用了Runnable接口的,两者之间的区别在于我们一个是通过继承去引用,一个是使用接口去引用。
从而两者体现出来的不同最主要在继承和接口的区别
1、实现接口可以理解为是java对单继承的补充;
2、当子类继承父类,就自动拥有父类的功能,方法;
3、如果子类需要扩展功能,可以通过实现接口的方式扩展
解决的问题不同:
继承的价值主要在于:解决代码的复用性和可维护性。
接口的价值主要在于:设计,设计好各种规范(方法),让其它类去实现这些方法;接口比继承更加灵活:接口比继承更加灵活,继承是满足is - a的关系,而接口只需满足like - a的关系。
接口在一定程度上实现代码解耦[即:接口规范性+动态绑定]
所以在使用方面
不建议使用 继承Thread类的方法,因为可以避免OOP单继承局限性
推荐使用实现Runnable接口,因为可以避免单继承局限性,灵活方便,方便同一个对象被多个线程使用。
// Callable的源码
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
Callable接口最主要与Runnable接口对比,(因为Thread也是使用Runnable接口的)
两者最大的区别在于Callable可以抛出异常,同时可以返回值。
在线程池的运行方面也是有所不同的。
Callable接口的启动
ExecutorService ser = Executors.newFixedThreadPool(1);
Future<Object> future = ser.submit(new Thread3());
try {
Object result = future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
ser.shutdown();
Runnable接口的启动
ExecutorService ser = Executors.newFixedThreadPool(1);
ser.execute(new Thread2());
ser.shutdown();