zoukankan      html  css  js  c++  java
  • Java基础—实现多线程的三种方法

    Java虚拟机(JVM,是运行所有Java程序的抽象计算机,是Java语言的运行环境)允许应用程序并发地运行多个线程。在Java语言中,多线程的实现一般有以下三种方法:

    1、实现Runnable接口,并实现该接口的run()方法。

      ①自定义类并实现Runnable接口,实现run()方法。

      ②创建Thread对象,用实现Runnable接口的对象作为参数实例化该Thread对象。

      ③调用Thread的start()方法。

    class MyThread implements Runnable{  //创建线程类
        @Override
        public void run() {
            System.out.println("Thread body");
        }
    }
    public class Test {
        public static void main(String[] args) {
            MyThread thread = new MyThread();
            Thread t = new Thread(thread);
            t.run();  //开启线程
        }
    }

    2、继承Thread类,重写run()方法。

      Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()方法。start()方法是一个native(本地)方法,它将启动一个新线程,并执行run()方法(Thread中提供的run()方法是一个空方法)。这种方式通过自定义类直接extends Thread,并重写run()方法,就可以启动新线程并执行自己定义的run()方法。需要注意的是,当start()方法调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行多线程代码是由操作系统决定的。

    class MyThread extends Thread {    //创建线程类
        @Override
        public void run() {
            System.out.println("Thread body");    //线程的方法体
        }
    }
    public class Test {
        public static void main(String[] args) {
            MyThread thread = new MyThread();
            thread.run();    //开启线程
        }
    }

    3、实现Callable接口,重写call()方法。

      Callable对象实际是属于Executor框架中的功能类,Callable接口与Runnable接口类似,但是提供了比Runnable更强大 的功能,主要表现为以下三点:

      ①Callable可以在任务结束后提供一个返回值,Runnable无法提供这个功能。

      ②Callable中的call方法可以抛出异常,而Runnable的run()方法不能抛出异常。

      ③运行Callable可以拿到一个Future对象,Future对象表示异步计算的结果。它提供了检查计算是否完成的方法。由于线程属于异步计算模型,所以无法从其他线程中得到方法的返回值,在这种情况下,就可以使用Future来监视目标线程调用call()方法的情况,当调用Future的get()方法以获取结果时,当前线程就会阻塞,直到call()方法结束返回结果。

    import java.util.concurrent.*;
    public class CallableAndFuture{  //创建线程类
        public static class CallableTest implements Callable<String>{
            @Override
            public String call() throws Exception {
                return "Hello World!";
            }
        }
        public static void main(String[] args) {
            ExecutorService threadPool = Executors.newSingleThreadExecutor();
            //启动线程
            Future<String> future = threadPool.submit(new CallableTest());
            try{
                System.out.println("waiting thread to finish");
                System.out.println(future.get());  //等待线程结束,并获取返回结果
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    上述程序的运行结果为:

    waiting thread to finish
    Hello World!

      在以上三种方式中,前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。当需要实现多线程时,一般推荐实现Runnable接口的方式,原因如下:首先,Thread类定义了多种方法可以被派生类使用或重写,但是只有run方法是必须被重写的,在run方法中实现这个线程的主要功能。这当然是实现Runnable接口所需的同样的方法。而且,很多Java开发人员认为,一个人仅在它们需要被加强或修改时才会被继承。因此,如果没有必要重写Thread类中的其他方法,那么通过继承Thread的实现方式和实现Runnable接口的效果相同,在这种情况下最好通过Runnable接口的方式来创建线程。

  • 相关阅读:
    prototype.js超强的javascript类库
    MySQL Server Architecture
    Know more about RBA redo block address
    MySQL无处不在
    利用Oracle Enterprise Manager Cloud Control 12c创建DataGuard Standby
    LAMP Stack
    9i中DG remote archive可能导致Primary Database挂起
    Oracle数据库升级与补丁
    Oracle为何会发生归档日志archivelog大小远小于联机重做日志online redo log size的情况?
    Oracle Ksplice如何工作?How does Ksplice work?
  • 原文地址:https://www.cnblogs.com/myl0205/p/11376323.html
Copyright © 2011-2022 走看看