【Java学习笔记】多线程的三种实现方式

多线程

Java中共有三种多线程的实现方式,实现多线程主要有两种途径

  • 继承Tread类
  • 实现Runable接口(Callable接口)

继承Thread类

Tread类是一个支持多线程的功能类,只要有一个子类它就可以实现多线程的功能。

class MyThread extends Thread {
    public void run() {
        //线程主体操作
    }
}

public class TestMain {
    public static void main(String[] args) {
        MyThread mt1 = new MyTread();
        mt1.start();        //不是调用run()方法!!!
        MyThread mt2 = new MyTread();
        mt2.start()
    }
}

run()方法是线程的主体操作方法,而多线程启动调用的是start()方法。
但如果某一个线程对象重复进行了启动,那么会抛出“IllegalThreadStateException”异常。

为什么要使用start()方法来启动线程?

​ 使用Thread类的start()方法不仅仅要启动多线程的执行代码,还要根据不同的操作系统进行资源分配。

实现Runnable接口

虽然Thread类可以实现多线程的主体类定义,但Java只能够单继承,所以为了解决单继承的限制,所以提供了Runnable接口。它是FunctionalInterface接口(函数式接口),所以只包含有一个方法。

public interface Runnable {
    public void run();
}

使用方法与继承Thread方式基本类似,都是将主体操作防止在run()方法中,但有有一个严重的区别:Runnable接口中并没有start()方法的实现,所以想要启动多线程一定得依靠Thread类完成。

在Thread类中有如下构造方法:

public Thread(Runnable target)

所以代码应该如下:

class MyTread implements Runnable{
    public void run() {
        //线程主体操作
    }   
}

public class TestMain {
    public static void main(String[] args) {
        MyThread mt1 = new MyTread();
        new Thread(mt1).start();    //启动多线程
        new Thread(mt1).start();
    }
}

利用Runnable接口,我们可以使多个线程对象都直接占用了同一个MyThread对象引用,即多个线程对象都直接访问同一个数据资源,即实现了数据共享。

多线程两种实现方式的区别?

首先使用Runnable接口与Thread类相比,解决了单继承的局限,所以如果要使用,一定使用Runnable接口。

  • Thread类是Runnable接口的子类,使用Runnable接口实现多线程可以避免单继承局限。
  • Runnable有着更好的数据共享。

Callabel

虽然Runnable接口实现的多线程不能返回操作结果,所以Callable接口的出现就是为了解决这一矛盾。它包含在java.util.concurrent.Callable包中。

public interface Callable<V> {
    public V call() throw Exception;
}

使用方式:

class MyTread implements Callable<String>{
    private int ticket = 10;
    public String call() {
        for(int i = 0; i < 100; i++) {
            if(this.ticket > 0) {
                System.out.println("卖票!ticket = " + this.ticket--);
            }
        }
        return "票卖光了!";
    }
}

public class TestMain {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        MyTread mt1 = new MyTread();
        MyTread mt2 = new MyTread();

        //FutureTask是Runnable接口子类,所以可以使用Thread类的构造来接受task对象
        FutureTask<String> task1 = new FutureTask<String>(mt1);
        FutureTask<String> task2 = new FutureTask<String>(mt2);

        //启动多线程
        new Thread(task1).start();
        new Thread(task2).start();

        //多线程执行完毕后,开一通过FutrueTask的父接口Future中的get()方法完成
        System.out.println("A线程的返回结果 = " + task1.get());
        System.out.println("A线程的返回结果 = " + task2.get());
    }
}

Thread类里没有直接支持Callable接口的多线程应用。而在java.util.concurrent.FutureTask类中有提供对Callable接口对象的操作。在FutureTask类里面定义有如下的构造方法:

public FutureTask(Callable<V> callable)

所以我们可以通过FutreTask对象取得线程的返回值。

猜你喜欢

转载自blog.csdn.net/qq_34802416/article/details/79865857