Java多线程学习笔记_多线程的实现方式

多线程的实现方案:

  1. 继承 Thread类 的方式实现。
  2. 实现 Runnable接口 的方式实现。
  3. 利用 Callable接口 和 Future接口 的方式实现。

方案1:继承Thread类

  1. 定义一个 MyThread类 继承 Thread类。
  2. 在 MyThread类 中重写 run()方法。
  3. 创建 MyThread类 的对象。
  4. 启动线程。
public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("线程开始了" + i);
        }
    }
}


public class Demo {
    public static void main(String[] args) {
        MyThread m1 = new MyThread();
        MyThread m2 = new MyThread();
        m1.start();
        m2.start();
    }
}

  • 为什么要重写run()方法?

因为run()被用来封装线程需要执行的代码。

  • run()方法和start()方法的区别?

run()表示的仅仅是创建对象,调用对象的方法,并没有开启线程。

start()表示与系统资源进行交互,开启一条线程。


 方法二:实现Runnable接口

  1. 定义一个MyRunnable类实现Runnable接口。
  2. 在MyRunnable类中重写run()方法。
  3. 创建MyRunnable类的对象。
  4. 创建Thread类的对象,并把MyRunnable类的对象作为构造方法的参数传入。
  5. 启动线程。
public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("第二种方法实现多线程" + i);
        }
    }
}

public class Demo {
    public static void main(String[] args) {

        MyRunnable mr1 = new MyRunnable();//创建了一个参数的对象。
        Thread t1 = new Thread(mr1);//创建了一个线程对象,并把参数传递给这个线程。
        t1.start();//在线程启动之后执行的是参数里面的run()方法。

        MyRunnable mr2 = new MyRunnable();
        Thread t2 = new Thread(mr2);
        t2.start();
    }
}

 方式三:实现Callable接口和Future接口

  1. 定义MyCallable类实现Callable接口。
  2. 在MyCallable类中重写call()方法。
  3. 创建MyCallable类的对象
  4. 创建 Future类 的实现类 FutureTask类 的对象,把MyCallable类的对象作为构造方法的参数传入。
  5. 创建Thread类的对象,并把FutureTask对象作为构造方法的参数。
  6. 启动线程。
//这里的泛型中的数据类型和下面call()方法的返回值类型一致
//想要返回什么数据,就写对应的数据类型
public class MyCallable implements Callable<String> {

    @Override
    public String call() throws Exception {
        for (int i = 0; i < 100; i++) {
            System.out.println("第" + i + "次表白");
        }
        return "I DO.";
    }
}

public class Demo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //线程开启后需要执行里面的call()方法        
        MyCallable mc = new MyCallable();
        //好比一个中间媒介
        //既可以获取线程执行完毕的结果,也可以作为参数传递给Thread对象。
        FutureTask<String> ft = new FutureTask<>(mc);
        //创建线程对象        
        Thread t = new Thread(ft);
        //开启线程
        t.start();
        System.out.println(ft.get());
    }
}

 FutureTask类既实现了Future接口也实现了Runnable接口,详细可查官方文档,故可以作为参数传入Thread的构造方法。

注意:get()方法要在线程开启之后调用。


三种方式的对比

 

  优点 缺点
实现接口 实现Runnable接口(没有返回值) 扩展性强,实现该接口的同时还可以继承其他的类。 编程相对复杂,不能直接使用Thread类中的方法。
实现Callable接口(有返回值)
继承Thread类

编程比较简单,

可以直接使用Thread类中的方法。

可扩展性差,

不能再继承其他的类。

猜你喜欢

转载自blog.csdn.net/qq_43191910/article/details/114818828