java多线程 ---- 创建线程

创建线程和启动

  • 继承 Thread
  • 实现 Runable
  • 实现 Callable

继承Thread类创建线程类

通过继承Thread类创建线程类的具体步骤和具体代码如下:

  1. 定义一个继承Thread类的子类,并重写该类的run()方法;
  2. 创建Thread子类的实例,即创建了线程对象;
  3. 调用该线程对象的start()方法启动线程。
class MyThread extends Thread   {
	 // 步骤1:继承Thread类重写run()方法
	@Override 
    public void run()   { 
     //do something here  
    }  
 } 
 
public static void main(String[] args){
 //步骤2:创建Thread子类,即创建了线程对象
 MyThread myThread = new MyThread ();   
 // 步骤3:启动线程   
 myThread .start(); 
}

实现Runnable接口创建线程类

通过实现Runnable接口创建线程类的具体步骤和具体代码如下:

  1. 定义Runnable接口的实现类,并重写该接口的run()方法
  2. 创建Runnable实现类的实例,并以此实例作为Thread的target对象,即该Thread对象才是真正的线程对象
public class Main {
    public static void main(String[] args) {
    	 // 将Runnable实现类作为Thread的构造参数传递到Thread类中,然后启动Thread类
        MyRunnable runnable = new MyRunnable();
        new Thread(runnable).start();
    }
}

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());
    }
}

两种方式在本质上没有明显的区别,在外观上有很大的区别,第一种方式是继承Thread类,因Java是单继承,如果一个类继承了Thread类,那么就没办法继承其它的类了,在继承上有一点受制,有一点不灵活,第二种方式就是为了解决第一种方式的单继承不灵活的问题,所以平常使用就使用第二种方。

通过Callable和Future创建线程

通过Callable和Future创建线程的具体步骤和具体代码如下:

  1. 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值
  2. 创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值
  3. 使用FutureTask对象作为Thread对象的target创建并启动新线程
  4. 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值其中
public class Main {
    public static void main(String[] args) throws Exception {
    	 // 步骤2:将Callable包装成FutureTask,FutureTask也是一种Runnable
        MyCallable callable = new MyCallable();
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        //步骤3:使用FutureTask对象作为Thread对象的target创建并启动新线程
        new Thread(futureTask).start();

        // 步骤4:调用FutureTask对象的get()方法来获得子线程执行结束后的返回值其中
        Integer sum = futureTask.get();
        System.out.println(Thread.currentThread().getName() + Thread.currentThread().getId() + "=" + sum);
    }
}


class MyCallable implements Callable<Integer> {
	// 步骤1:创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值
    @Override
    public Integer call() throws Exception {
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId() + "\t" + new Date() + " \tstarting...");

        int sum = 0;
        for (int i = 0; i <= 100000; i++) {
            sum += i;
        }
        Thread.sleep(5000);

        System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId() + "\t" + new Date() + " \tover...");
        return sum;
    }
}

三种方式比较

  • Thread: 继承方式, 不建议使用, 因为Java是单继承的,继承了Thread就没办法继承其它类了,不够灵活
  • Runnable: 实现接口,比Thread类更加灵活,没有单继承的限制
  • Callable: Thread和Runnable都是重写的run()方法并且没有返回值,Callable是重写的call()方法并且有返回值并可以借助FutureTask类来判断线程是否已经执行完毕或者取消线程执行
  • 当线程不需要返回值时使用Runnable,需要返回值时就使用Callable,一般情况下不直接把线程体代码放到Thread类中,一般通过Thread类来启动线程
  • Thread类是实现Runnable,Callable封装成FutureTask,FutureTask实现RunnableFuture,RunnableFuture继承Runnable,所以Callable也算是一种Runnable,所以三种实现方式本质上都是Runnable实现
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值