实现多线程的三种方式:Thread类、Runnable接口、Callable接口实现多线程

继承java.lang.Thread(JDK1.0)类,覆写run()方法

无论哪种方式实现多线程,线程启动 一律按照Thread类提供的start()方法
start()才会让多个线程交替执行,run()只会让每个线程都执行自己的

start()方法详解
1.进方法之后判断线程状态,为0表示没启动,否则抛出IllegalThreadStateException(RunTimeException)。所以一个线程只能启动一次
2.调用本地方法start0()来将线程真正启动。(通过start0()调run())
3.JVM为线程准备好资源后,回调run()方法来执行具体任务

在这里插入图片描述

  • 缺点:单继承局限
//继承Thread来实现多线程
class MyThread2 extends Thread {
    private int ticket = 20;
    private String title;

    public MyThread2(String title) {
        this.title = title;
    }

    public void run() {
        while (ticket > 0) {
            System.out.println("当前线程为"+title+"剩余票数为"+ticket--);
        }
    }
}
public class TestThread {
    //1.实现Runnable来实现多线程

    //2.继承Thread来实现多线程
    public static void main(String[] args) {
        MyThread2 myThread2 = new MyThread2("myThread2");    //1.创建真实线程类
        MyThread2 myThread22 = new MyThread2("myThread2");    //1.创建真实线程类
        MyThread2 myThread23 = new MyThread2("myThread23");    //1.创建真实线程类

        //Thread类提供的构造可接收Runnable的对象
        Thread thread1 = new Thread(myThread2);    //2.三个代理线程类共享一个线程 20张票
        Thread thread2 = new Thread(myThread22);
        Thread thread3 = new Thread(myThread23);
        thread1.start();    //3.启动线程
        thread2.start();
        thread3.start();
        thread3.start();
    }
}

实现Runnable接口,覆写run()方法

解决了单继承缺陷,利用Thread类的构造方法  public Thread(Runnable target)  传入Runnable对象调用start()方法
  • 代理设计模式:
    Thread类和实现了Runnable接口的自定义类
    其中Thread类实现辅助操作,包括线程里资源调度等任务,自定义线程类完成真实业务
//实现Runnable来实现多线程
class MyThread implements Runnable {
    private int ticket = 20;

    public void run() {
        while (ticket > 0) {
            System.out.println("当前线程为"+Thread.currentThread().getName()+"剩余票数为"+ticket--);
        }
    }
}

public class TestRunnable {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();    //1.创建真实线程类
        Thread thread1 = new Thread(myThread,"买票人A");    //2.三个代理线程类共享一个线程 20张票
        Thread thread2 = new Thread(myThread,"买票人B");
        Thread thread3 = new Thread(myThread,"买票人C");
        thread1.start();    //3.启动线程
        thread2.start();
        thread3.start();
    }
}


继承Thread与实现Runnable的区别

1.Thread类有单继承缺陷,Runnable更加灵活;且Thread类也实现了Runnable接口,覆写其run()方法
2.实现Runnable接口可以更好的(相比而言更容易)实现程序共享的概念
比如卖票 
假设创建两个Thread对象卖票 (new Thread().start),他俩会各卖个的;
但如果在这两个Thread对象new的过程中传入同一个Runnable子类对象(new Thread(runObj).start)。则会卖同一套票。

实现Callable接口,覆写call()方法

T call()方法有返回值,其返回值类型与Callable<T>接口的泛型类型一致
Callable接口和Thread没有直接联系,如何使用其start()方法呢?
Callable接口是Future的子接口。Future的get()方法可以拿到call方法的返回值
FutureTask类既实现了Future接口,又实现了Runnable接口。 
FutureTask提供的构造方法允许传入Callable对象。
Thread类提供的构造方法允许传入Runnable对象->即可以将FutureTask子类传入,达到调用start()的目的。
  • 类图
    在这里插入图片描述
class MyThread3 implements Callable<String> {
    private Integer ticket = 20;
    @Override
    public String call() throws Exception {
        while (this.ticket > 0) {
            System.out.println(Thread.currentThread().getName()+"当前剩余票数为"+this.ticket--);
        }
        return "票已售完,下次赶早~";
    }
}
public class TestCallable {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //1.有一个MyThread3对象
        MyThread3 myThread3 = new MyThread3();
        //2.有一个FutureTask对象接收callable 的返回值
        FutureTask<String> futureTask =new FutureTask<>(myThread3);
        //3.有一个Thread对象来启动线程,通过传入Future对象间接传入call()
        Thread thread = new Thread(futureTask);
        thread.start();
        System.out.println(futureTask.get());

    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值