1. 实现Java多线程

有三种使用线程的方法:

  • 实现 Runnable 接口;
  • 实现 Callable 接口;
  • 继承 Thread 类。

实现 Runnable 和 Callable 接口的类只能当做一个可以在线程中运行的任务,不是真正意义上的线程,因此最后还需要通过 Thread 来调用。可以说任务是通过线程驱动从而执行的。

1.1 继承Thread类,重写run()方法;

class MyThread extends Thread{
    public void run(){
        System.out.println("Thread body");
    }
}

public class Test{
    public static void main(String[] args){
        MyThread thread=new MyThread();
        thread.start();
    }
}

1.2 实现Runnable接口,并实现该接口的run()方法;

推荐这个!!(实现这个接口的类还可以继承自其它的类,用3.1就没有办法再去继承别的类)

Step1:自定义类并实现Rubbale接口,实现run()方法;

Step2:创建Thread对象,用实现Runnable接口的对象作为参数实例化Thread对象;

Step3:调用Thread的start()方法。

class MyThread implements Runnable{
    public void run(){
        System.out.println("Thread body");
    }
}

public class Test{
    pulic static void main(String[] args){
        MyThread thread=new MyThread();
        Thread t=new Thread(thread);
        t.start();
    }
}

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

Callable接口实际上是属于Executor框架中的功能类.

Callable接口与Runnable接口的功能类似,提供了比Runnable更强大的功能,主要表现有三点:

  1. Callable可以在任务结束之后提供一个返回值,返回值通过 FutureTask 进行封装,Runnable则不能;
  2. Callable接口中的call()方法可以抛出异常,而Runnable()的run()方法不能抛出异常;
  3. 运行Callable可以拿到一个Future对象,Future对象表示异步计算的结果,提供了检查计算是否完成的方法。当调用future的get()方法以获取结果时,当前线程就会阻塞,直到call()方法结束返回结果。
public static class CallableTest implements Callable<String>{
    @Override
    public String call() throws Exception {
        return "hello word";
    }
}
	
public static void main(String[] args) {		
    ExecutorService threadPool = Executors.newSingleThreadExecutor();//1.创建线程池
    Future<String> future = threadPool.submit(new CallableTest());//2.提交任务
    System.out.println("waiting thread to finish");
    try {
        System.out.println(future.get());//3.获取返回值
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
}

运行结果:

java多线程并行调用接口获取结果 多线程接口 java_System

以上三种执行方式,前两种执行完后都没有返回值,最后一种带返回值。

当实现多线程时,一般推荐实现Runnable接口。

一个类是否可以同时继承Thread与实现Runnable?

可以。

public class Test extends Thread implements Runnable{
    public static void main(String[] args){
        Thread t=new Thread();
        t.start();
    }
}

其中,Test类从Thread类继承的run()被认为是对Runnable接口中run()的实现。

1.4 三种实现方式的比较

  • 实现Runnable接口:
  • 可以避免Java单继承特性而带来的局限;
  • 增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的;
  • 适合多个相同程序代码的线程区处理同一资源的情况。
  • 继承Thread类和实现Runnable方法启动线程都是使用start方法,然后JVM虚拟机将此线程放到就绪队列中,如果有处理机可用, 则执行run方法。
  • 实现Callable接口要实现call方法,并且线程执行完毕后会有返回值。其他的两种都是重写run方法,没有返回值。