创建线程有哪几种方式?

创建线程有三种方式,分别是继承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

原文地址:http://www.cnblogs.com/galo/p/16925572.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性