Java创建线程的5种方式

实现方式

  • 继承Thread类
  • 实现Runnable接口
  • 实现Callable接口
  • 使用线程池ThreadPoolExecutor
  • 使用匿名内部类 new Thread或者lambda表达式

继承Thread类

  1. 创建一个继承于Thread类的子类
  2. 重写Thread类的run() –> 将此线程执行的操作声明在run()中
  3. 创建Thread类的子类的对象
  4. 通过此对象调用start()执行线程
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class MyThread extends Thread {
    public void run() {
    System.out.println("Thread is running...");
    }
    }

    public class Main {
    public static void main(String[] args) {
    MyThread thread = new MyThread();
    thread.start(); // 启动线程
    }
    }

实现Runnable接口

  1. 创建一个实现了Runnable接口的类
  2. 实现类去实现Runnable中的抽象方法:run()
  3. 创建实现类的对象
  4. 将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
  5. 通过Thread类的对象调用start()
    ②调用当前线程的run()–>调用了Runnable类型的target的run()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class MyRunnable implements Runnable {
    public void run() {
    System.out.println("Thread is running...");
    }
    }

    public class Main {
    public static void main(String[] args) {
    Thread thread = new Thread(new MyRunnable());
    thread.start(); // 启动线程
    }
    }

实现Callable接口

  1. 创建一个实现Callable的实现类
  2. 实现call方法,将此线程需要执行的操作声明在call()中
  3. 创建Callable接口实现类的对象
  4. 将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象
  5. 将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
  6. 获取Callable中call方法的返回值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    class MyCallable implements Callable<String> {
    public String call() {
    return "Thread is running...";
    }
    }

    public class Main {
    public static void main(String[] args) {
    // 创建Callable实现类的实例
    Callable<String> callable = new MyCallable();

    // 创建FutureTask对象,用于包装Callable对象
    FutureTask<String> futureTask = new FutureTask<>(callable);

    // 创建线程并启动
    Thread thread = new Thread(futureTask);
    thread.start();

    try {
    // 获取线程执行结果
    String result = futureTask.get();
    System.out.println(result);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }

使用线程池ThreadPoolExecutor

  1. 创建好实现了Runnable接口的类或实现Callable的实现类
  2. 实现run或call方法
  3. 创建线程池
  4. 调用线程池的execute方法执行某个线程,参数是之前实现Runnable或Callable接口的对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    class MyPoolThread implements Runnable {
    @Override
    public void run() {
    System.out.println(Thread.currentThread().getName() + ": " + i);
    }
    }

    public class ThreadPool {

    public static void main(String[] args) {
    //1. 提供指定线程数量的线程池
    ExecutorService service = Executors.newFixedThreadPool(10);

    //输出class java.util.concurrent.ThreadPoolExecutor
    System.out.println(service.getClass());

    ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
    //自定义线程池的属性
    // service1.setCorePoolSize(15);
    // service1.setKeepAliveTime();

    //2. 执行指定的线程的操作。需要提供实现Runnable接口或Callable接口实现类的对象
    service.execute(new NumberThread());//适用于Runnable
    service.execute(new NumberThread1());//适用于Runnable
    // service.submit(Callable callable);//适合使用于Callable

    //3. 关闭连接池
    service.shutdown();
    }

    }

线程池常见参数

  • corePoolSize(核心线程数): 任务队列未达到队列容量时,最大可以同时运行的线程数量。
  • maximumPoolSize(最大线程数) : 任务队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。
  • workQueue(任务队列): 新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。

    无界队列-LinkedBlockingQueue 同步队列-SynchronousQueue 延迟阻塞队列-DelayedWorkQueue

  • keepAliveTime(存活时间):线程池中的线程数量大于 corePoolSize 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了 keepAliveTime才会被回收销毁。
  • unit(存活时间的单位) : keepAliveTime 参数的时间单位。
  • threadFactory(线程工厂) :用来创建线程,一般默认即可
  • handler(拒绝策略) :提交的任务过多而不能及时处理时,我们可以定制策略来处理任务

使用匿名内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Main {
public static void main(String[] args) {
//匿名内部类
Thread thread = new Thread(new Runnable() {
public void run() {
System.out.println("Thread is running...");
}
});
thread.start(); // 启动线程

//lambda
Thread thread = new Thread(() -> {
System.out.println("Thread is running...");
});
thread.start(); // 启动线程
}
}