java中线程的几种实现方式

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策略接口来让我们实现可返回值的线程实现。

猜你喜欢

转载自www.cnblogs.com/liwangcai/p/11876740.html