实现多线程的4种方式

实现多线程的4种方式

使用实现多线程有四种方式:

  • 继承 Thread 类;

  • 实现 Runnable 接口;

  • 使用 Callable 和 FutureTask 实现有返回值的多线程;

  • 使用 ExecutorService 和 Executors 工具类实现线程池(如果需要线程的返回值,需要在线程中实现 Callable

    和 Future 接口)

1.1 继承 Thread 类

Thread 类本质上是实现了 Runnable 接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过

Thread 类的 start() 实例方法,start() 方法是一个 native 方法,它将启动一个新线程,并执行 run() 方法。

继承 Thread 类的优点:简单,且只需要实现父类的 run 方法即可( start 方法中含有 run 方法,会创建一个新的

线程,而 run 是执行当前线程)。

继承 Thread 类的缺点:Java 的单继承,如果对象已经继承了其他的类则不能使用该方法,且不能获取线程的返回

值。

package com.multithreading;

public class ThreadDemo {
    public static void main(String[] args) {
        MyThread1 myThread1 = new MyThread1();
        MyThread1 myThread2 = new MyThread1();
        myThread1.start();
        myThread2.start();
    }

}

class MyThread1 extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
# 程序输出
Thread-1
Thread-0

1.2 实现 Runnable 接口

实现 Runnable 接口优点:简单,实现 Runnable 接口必须实现 run 方法。

实现 Runnable 接口缺点:创建一个线程就必须创建一个 Runnable 的实现类,且不能获取线程的返回值。

package com.multithreading;

public class RunnableDemo {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName());
        Thread t1 = new Thread(new MyThread2());
        t1.start();
    }
}

class MyThread2 implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
# 程序输出
main
Thread-0

1.3 使用 Callable 和 FutureTask

CallabTask 优点:可以获取多线程的返回值。

CallabTask 缺点:每个多线程都需要创建一个 Callable 的实现类。

package com.multithreading;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class CallableDemo {

    public static void main(String[] args) {
        FutureTask<String> futureTask = new FutureTask<>(new CallerTask());
        new Thread(futureTask).start();
        try {
            String result = futureTask.get();
            System.out.println(result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

class CallerTask implements Callable<String> {
    @Override
    public String call() {
        return Thread.currentThread().getName();
    }
}
# 程序输出
Thread-0

1.4 使用 ExecutorService 和 Executors

线程池 ExecutorService 和工具类 Executors 优点:可以根据实际情况创建线程数量,且只需要创建一个线程池即

可,也能够通过 Callable 和 Future 接口得到线程的返回值,程序的执行时间与线程的数量紧密相关。

线程池 ExecutorService 和工具类 Executors 缺点:需要手动销毁该线程池(调用shutdown方法)。

package com.multithreading;

import java.util.concurrent.Callable;

public class MyTask implements Callable<String> {

    private final int id;

    public MyTask(int id) {
        this.id = id;
    }

    @Override
    public String call() {
        return "result of TaskWithResult: " + id;
    }
}
package com.multithreading;

import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ExecutorServiceDemo {

    static final int NUMBER = 10;

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        ArrayList<Future<String>> results = new ArrayList<>();
        for (int i = 0; i < NUMBER; i++) {
            results.add(exec.submit(new MyTask(i)));
        }
        exec.shutdown();
        for (Future<String> future : results) {
            try {
                System.out.println(future.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
}
# 程序输出
result of TaskWithResult: 0
result of TaskWithResult: 1
result of TaskWithResult: 2
result of TaskWithResult: 3
result of TaskWithResult: 4
result of TaskWithResult: 5
result of TaskWithResult: 6
result of TaskWithResult: 7
result of TaskWithResult: 8
result of TaskWithResult: 9

你可能感兴趣的:(java,java)