zoukankan      html  css  js  c++  java
  • 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策略接口来让我们实现可返回值的线程实现。

  • 相关阅读:
    安卓学习57
    安卓学习56
    安卓学习55
    安卓学习54
    安卓学习53
    安卓学习52
    安卓学习51
    安卓学习50
    安卓学习49
    安卓学习48
  • 原文地址:https://www.cnblogs.com/liwangcai/p/11876740.html
Copyright © 2011-2022 走看看