java多线程(一)创建线程的三种方法及比较

Java创建线程有三种方法

  1. 继承Thread类
  2. 实现Runnable接口
  3. 实现Callable接口

一 . 继承Thead类

  • 继承Thea的类后我们要重写一个run()方法,这个run()方法里面的内容就是开辟新线程要执行的内容。
  • 注意,虽然新线程是执行run()方法里面的内容,但不能直接调用run(),那样就变成了普通的对象方法的调用,并不会创建出新的线程去执行run()方法里面的内容,正确做法是调用start()方法创建新线程。
  • 一般步骤是
    • 继承Thread类重写run()方法;
    • 创建继承了Thread类的对象;
    • 调用这个对象的start()方法。
public class testThread {
    public static void main(String[] args) {
        //创建Test类通过调用start()方法启动新线程
        Test test = new Test();
        test.start();
        for (int i=0;i<50;i++) {
            System.out.print(1);
        }
    }
}
//这个类要继承Thread类并且重写run方法
class Test extends Thread{
    public void run(){
        for (int i=0;i<50;i++) {
            System.out.print(2);
        }
    }
}

  • 运行结果
11111111111111111111111122222222222222222222222222222222222222222222222222222222111111111111212121212121222222222222222222222222222222222222221111111111111111111111111111111111111111111111111111111111
Process finished with exit code 0

  • 注:这里运行结果每次都会不一样,因为start()方法会根据CPU来执行哪条线程。

二 . 实现Runnable接口

  • 这个Runnable接口同继承Thread类有很大的相似,也要重写run()方法,但是因为Runnable接口没有start()方法,所以需要调用Thread对象的start()方法。
  • 一般步骤是
    • 实现Runnable接口并重写run()方法;
    • 创建实现了Runnable接口的类的对象;
    • 创建Thread对象(这里要将前面创建的对象当作参数传入Thread里);
    • 调用Thread对象的start()方法。
public class testRunnable {
    public static void main(String[] args) {
        //创建带有实现Runnable类的参数的Thread对象,直接调用thread对象的start()方法
        Test1 test = new Test1();
        Thread thread = new Thread(test);
        thread.start();
        for (int i=0;i<100;i++) {
            System.out.print(1);
        }
    }
}
//这个类要实现Runnable接口,并重写run()方法
class Test1 implements Runnable{
    public void run(){
        for (int i=0;i<100;i++) {
            System.out.print(2);
        }
    }
}

三 . 实现Callable接口

  • 实现Callable接口要重写call()方法,call()方法相当于前面的run()方法,是线程的执行体。但call()方法功能更强大,它有返回值,并且可以抛出异常。
  • 一般步骤是
    • 实现Callable接口并重写call()方法;
    • 创建FutureTask类来包装Callable对象;
    • 使用FutureTask对象作为Thread对象的target创建并启动线程(因为FutureTask实现了Runnable接口);
    • 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class testCallable {
    public static void main(String[] args) {
        Test1 test = new Test1();
        FutureTask task = new FutureTask(test,"sad");
        Thread thread = new Thread(task);
        thread.start();
        for (int i=0;i<100;i++) {
            System.out.print(1);
        }
        //获取返回值
        try {
            String a = (String) task.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}
//这个类要实现Callable接口,并重写call()方法
class Test2 implements Callable {
    public String call(){
        for (int i=0;i<100;i++) {
            System.out.print(2);
        }
        return "aaa";
    }
}

四 . 三种方的法比较

  • 继承Thread类是最简单的一种方法,但由于Java不能多继承,因此有很大的局限性
  • 实现Runnable接口也是比较简单的一种方法,并且没有单继承的局限性。
  • 实现Callable接口这个方法比较复杂,但是功能强大。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值