1. 继承Thread类来实现
class MyThread extends Thread{ @Override public void run() { System.out.println("myThread is running"); } }
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
由于在java中采用单继承的模式,因此继承Thread类有一个明显的缺点就是占用了唯一的extends,是的我们无法在继承其它的类,因此一般不会采用这种方式。
2. 实现Runnable接口
class MyRun implements Runnable{ @Override public void run() { System.out.println("myThread is running"); } }
public static void main(String[] args) {
// MyThread thread = new MyThread();
// thread.start();
Thread thread1 = new Thread(new MyRun());
thread1.start();
}
我们通过Runnable接口来实现线程实际上是策略模式的实现(策略模式可以参考我之前写的博客)。我们通过实现 run()来实现自己要完成的事情。
3. 通过Callable来实现可返回值的线程
class MyCallable implements Callable{ //实现接口Callable @Override public Object call() throws Exception { return "my callable is running"; } }
public static void main(String[] args) throws ExecutionException, InterruptedException {
// MyThread thread = new MyThread();
// thread.start();
// Thread thread1 = new Thread(new MyRun());
// thread1.start();
FutureTask task = new FutureTask(new MyCallable()); //构造一个FutureTask,FutureTask间接继承了Runnable接口
Thread thread = new Thread(task);
thread.start();
System.out.println(task.get());
}
使用Callable接口相当于在run()方法的基础上再次使用了策略模式,将call()方法留了出来,用以实现并保存方法执行的结果。我们可以看一下源码。
public class FutureTask<V> implements RunnableFuture<V> { //这是FutureTask类,本身间接实现了Runnable接口
这是FutureTask中的run()方法
public void run() { if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return; try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { result = c.call(); //可以发现在FutureTask中的run方法中调用了call()方法,而这个call()方法通过构造器传入,我们可以自由实现。相当于也是策略模式的实现。 ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } if (ran) set(result); //在这里将线程运行的结果进行了保存 } } finally { // runner must be non-null until state is settled to // prevent concurrent calls to run() runner = null; // state must be re-read after nulling runner to prevent // leaked interrupts int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } }
protected void set(V v) { //这是set()函数
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v; //在这里将返回值赋给了outcome
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
4. 总结
(1)继承Thread类后,我们需要重写run()方法来实现自己的线程。
(2)对于实现Runnable接口,该接口相当于是策略接口。
(3)对于实现Callable接口,在FutureTask中给出了run()方法的具体实现(FutureTask间接实现了Runnable接口),并且流出了另外的Callable策略接口来让我们实现可返回值的线程实现。