首页 > 技术文章 > 1、java中有几种方法可以实现一个线程?

ljk-shm-0208 2021-04-12 11:33 原文

有3种实现方法,继承Thread类、实现Runnable接口、通过Callable接口实现多线程

1.1 继承Thread类

步骤:

1)继承Thread 类

2)重写父类run 方法

3)在run方法编写线程需求做的代码块

4)实例化线程类

5)调用线程start(启动线程)

public class ThreadDemo extends Thread{
  /**
  * 1.继承Thread类
  * 2.重写run()方法
  */
  @Override
  public void run() {
    System.out.println("我来了!~~~~~~");
  }
  public static void main(String[] args) {
    ThreadDemo thread1 = new ThreadDemo();
    ThreadDemo thread2 = new ThreadDemo();
    thread1.start();//启动线程
    thread2.start();//启动线程
    //启动线程的唯一方法就是通过Thread类的start()实例方法。
    //start()方法是一个native方法,它将启动一个新线程,并执行run()方法。
  }
}

1.2 实现Runnable接口

步骤:

1)实现Runable 接口

2)重写父类run 方法

3)在run方法中编写线程需求做的代码块

4)实例化线程类

5)先实例化Thread再把线程通过构造方法传递调用线程start(启动线程)

public class MyThread extends OtherClass implements Runnable {

  public void run() {
  System.out.println("MyThread.run()");
  }
  }
}

//为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例:

MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();

1.3 通过Callable接口实现多线程

Java5之后,提供了Callable接口,看起来像是Runnable接口的增强版:该接口提供call()方法来作为线程执行体。与run()相比,call()方法更强大,该方法可以有返回值,并且可以声明抛出异常。

Callable接口介绍:

1)java.util.concurrent.Callable是一个泛型接口,只有一个call()方法

2)call()方法抛出异常Exception异常,且返回一个指定的泛型类对象

Callable接口实现多线程的应用场景:当父线程想要获取子线程的运行结果时

实现Callable和实现Runnable类似,但是功能更强大,具体表现在

a)可以在任务结束后提供一个返回值,Runnable不行;

b)call方法可以抛出异常,Runnable的run方法不行;

c)可以通过运行Callable得到的Fulture对象监听目标线程调用call方法的结果,得到返回值,(fulture.get(),调用后会阻塞,直到获取到返回值).

使用Callable接口实现多线程的步骤

1)第一步:创建Callable子类的实例化对象

2)第二步:创建FutureTask对象,并将Callable对象传入FutureTask的构造方法中(注意:FutureTask实现了Runnable接口和Future接口)

3)第三步:实例化Thread对象,并在构造方法中传入FurureTask对象

4)第四步:启动线程

//实现Callable重写call方法

public class CallTask implements Callable<Integer> {
@Override
public Integer call() throws Exception {
  int sum = 0;
  for (int i = 0; i < 100; i++) {
  sum += i;
}
  return sum;
  }
}
/**
 * 创建多线程的方式 : 4种
 * 1.继承Thread类
 * 2.实现Runable接口
 * 3.实现Callable接口
 * 4.使用线程池创建线程
 *
 *  Callable相比Runable的区别:
 *  1. 线程任务有返回值
 *  2. 需要使用FutureTask实现类接收返回值
 *  3. futureTask.get方法获取放回值时, 主线程会进入阻塞状态, 等待分线程的完成
 */
public class CallableTest {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        long start = System.currentTimeMillis();
        CallTask callTask = new CallTask();
        //使用FutureTask实现类接收返回值 泛型是返回值类型
        FutureTask<Integer> futureTask = new FutureTask<>(callTask);
        //new Thread(futureTask).start();
        for (int i = 0; i < 100; i++) {
            new Thread(futureTask).start();
        }
        // 主线程会进入阻塞状态, 等待分线程的完成  可以用于闭锁
        Integer sum = futureTask.get();
        System.out.println(sum);
        long end = System.currentTimeMillis();
        System.out.println("程序消耗时间: " + (end - start));
    }
}

 

 

推荐阅读