Live2D

实现多线程的三种方法

创建线程有哪几种方式?

创建线程有三种方式,分别是继承Thread类实现Runnable接口实现Callable接口

通过继承Thread类来创建并启动线程的步骤如下:

  1. 定义Thread类的子类,并重写该类的run()方法,该run()方法将作为线程执行体。

  2. 创建Thread子类的实例,即创建了线程对象。

  3. 调用线程对象的start()方法来启动该线程。

代码实现:

复制代码
public class MyThreadDemo{
    public static void main(String[] args) {
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
​
        //void start()到时此线程开始执行,java虚拟机调用此线程的run()方法
        my1.start();
        my2.start();
    }
}
复制代码
复制代码
public class MyThread extends Thread{
    
    //重写run方法
    @Override
    public void run() {
        for(int i=0;i<500;i++){
            System.out.println(i);
        }
    }
}
复制代码

 

 

通过实现Runnable接口来创建并启动线程的步骤如下:

  1. 定义Runnable接口的实现类,并实现该接口的run()方法,该run()方法将作为线程执行体。

  2. 创建Runnable实现类的实例,并将其作为Thread的target来创建Thread对象,Thread对象为线程对象。

  3. 调用线程对象的start()方法来启动该线程。

代码实现:

复制代码
public class MyRunnableDemo {
    public static void main(String[] args) {
//        1.定义一个类MyRunnable实现Runnable接口
//        2.在MyRunnable类中重写run()方法
//        3.创建MyRunnable类的对象
        MyRunnable my=new MyRunnable();
​
//        4.创建Thread类的对象,把MyRunnable对象作为构造方法的参数
        //Thread(Runnable target)
//        Thread t1=new Thread(my);
//        Thread t2=new Thread(my);
        //Thread(Runnable target,String name)
        Thread t1=new Thread(my,"高铁");
        Thread t2=new Thread(my,"飞机");
//        5.启动线程
        t1.start();
        t2.start();
    }
}
复制代码
public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

 

 

通过实现Callable接口来创建并启动线程的步骤如下:

  1. 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,且该call()方法有返回值。然后再创建Callable实现类的实例。

  2. 使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。

  3. 使用FutureTask对象作为Thread对象的target创建并启动新线程。

  4. 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。

    public static void main(String[] args) throws InterruptedException, ExecutionException {        
        MyCallable<String> mc=new MyCallable<String>();
        FutureTask<String> ft=new FutureTask<String>(mc);
        new Thread(ft).start();
        String result=ft.get();
        System.out.println(result);
    }
复制代码
    public class MyCallable<String> implements Callable<String> {
        private int tickt=10;
        @Override
        public String call() throws Exception {
            // TODO Auto-generated method stub
            String result;
            while(tickt>0) {
                System.out.println("票还剩余:"+tickt);
                tickt--;
            }
            result=(String) "票已卖光";
            return result;
        }
    }
复制代码

 

 

扩展阅读

通过继承Thread类、实现Runnable接口、实现Callable接口都可以实现多线程,不过实现Runnable接口与实现Callable接口的方式基本相同,只是Callable接口里定义的方法有返回值,可以声明抛出异常而已。因此可以将实现Runnable接口和实现Callable接口归为一种方式。

采用实现Runnable、Callable接口的方式创建多线程的优缺点:

  • 线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。

  • 在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型较好地体现了面向对象的思想

  • 劣势是,编程稍稍复杂,如果需要访问当前线程,则必须使用Thread.currentThread()方法。

采用继承Thread类的方式创建多线程的优缺点:

  • 劣势是,因为线程类已经继承了Thread类,所以不能再继承其他父类。

  • 优势是,编写简单,如果需要访问当前线程,则无须使用Thread.currentThread()方法,直接使用this即可获得当前线程。

鉴于上面分析,因此一般推荐采用实现Runnable接口、Callable接口的方式来创建多线程。

 

继承VS接口

实现接口会更好一些,因为:

Java 不支持多重继承,因此继承了 Thread 类就无法继承其它类,但是可以实现多个接口; 类可能只要求可执行就行,继承整个 Thread 类开销过大。

 

三种方式的区别

实现 Runnable 接口可以避免 Java 单继承特性而带来的局限;增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的;适合多个相同程序代码的线程区处理同一资源的情况。

继承相对来说编写简单,可以直接操纵线程;继承 Thread 类和实现 Runnable 方法启动线程都是使用 start() 方法,然后 JVM (Java虚拟机)将此线程放到就绪队列中,如果有处理机可用,则执行 run() 方法。

实现 Callable 接口要实现 call() 方法,并且线程执行完毕后会有返回值。其他的两种都是重写 run() 方法,没有返回值。

call()方法可抛出异常,而run()方法是不能抛出异常的。

Runnable ⾃ Java 1.0 以来⼀直存在,但 Callable 仅在 Java 1.5 中引⼊,⽬的就是为了来处理 Runnable 不⽀持的⽤例。 Runnable 接⼝不会返回结果或抛出检查异常,但是 Callable 接⼝ 可以。所以,如果任务不需要返回结果或抛出异常推荐使⽤ Runnable 接⼝,这样代码看起来会 更加简洁。

 

转载至:

https://blog.csdn.net/weixin_42606135/article/details/81282736

https://blog.csdn.net/weixin_44497034/article/details/115076996

posted @   都是朕的江山  阅读(336)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
返回顶端
点击右上角即可分享
微信分享提示