关于线程创建的方式

总结:
线程创建常用的方式有三种,分别是:

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

继承Thread类的方式

public class threadClassDemo extends Thread{
    int count = 1;
    @Override
    public void run() {
        count++;
        System.out.println("当前线程:"+Thread.currentThread().getName()+"\t count:"+count);
    }

    public static void main(String[] args) {

        for (int i=0;i<10;i++){
            threadClassDemo demo = new threadClassDemo();
            demo.start();
        }
    }
}

运行结果:
在这里插入图片描述

通过继承Thread类重写run方法,可以创建线程,上述demo中,main方法中创建了10个线程,count是线程类的实例变量,每个线程都对这个实例变量进行了操作,但是注意一点,这里的变量是不能实现线程之间的共享的,每个线程都有一个独立的count。

实现Runnable接口的方式

public class runnableDemo implements Runnable {
    int count = 0;
    @Override
    public void run() {
        System.out.println("当前线程:"+Thread.currentThread().getName());
        count++;
        System.out.println("count:"+count);
    }

    public static void main(String[] args) {

        for (int i= 0;i<10;i++){
            if(i==5){
                runnableDemo demo = new runnableDemo();
                new Thread(demo,"thread-one").start();
                new Thread(demo,"thread-two").start();
            }

        }
    }
}

运行结果:
在这里插入图片描述

上述demo中,通过实现Runnable接口的形式实现run方法,在run方法中编写线程执行体,创建2个线程,可以看到当创建两个线程的目标线程体共用一个时,count是会被两个线程共享的,线程体被共享;
也就是说通过实现Runnable接口的线程体再被多个线程调用时,资源是共享的,来验证一下:

public class runnableDemo implements Runnable {
    int count = 0;
    @Override
    public void run() {
        count++;
        try {
             TimeUnit.SECONDS.sleep(1);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
        System.out.println("当前线程:"+Thread.currentThread().getName()+"\t count:"+count);
    }

    public static void main(String[] args) {
        runnableDemo demo = new runnableDemo();
        for (int i= 0;i<10;i++){
            new Thread(demo,String.valueOf(i)).start();
        }
    }
}

上述代码中main方法中创建了十个线程,这10个线程共用一个demo线程体,也就是创建的线程都是执行的同一个线程体,这时运行结果呢?
在这里插入图片描述
如图,此时因为在线程体中对count的操作之后设置了一个等待时间,所以如果执行的结果大于2说明了count在10个线程中是共享的,结果也证实了count确实是共享的。

实现Callable接口方式

同样是为了创建线程,实现接口的方式创建还分为实现Runnable和Callable,这两者有什么不同呢?

class MyThread implements Runnable{
    @Override
    public void run() {

    }
class MyThread implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
       
        return 1024;
    }
}

上面创建了两个线程体,有什么不同呢?通过比较,我们发现大致有三点不同:

1、前者无返回值,后者有返回值
2、前者不会抛异常,后者会抛异常
3、方法名不一样
通过有返回值的线程,在执行多线程任务时,当任务执行失败,可以通过返回信息,完成任务的回滚等操作,当然线程执行有返回值还有很多的业务场景,这里不做详细解读。

class MyThread implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        System.out.println(Thread.currentThread().getName()+"\t ****MyThread-->call()****");
        return 1024;
    }
}
public static void main(String[] args) {
        try {
            FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyThread());
            Thread thread = new Thread(futureTask,"aaa");
            thread.start();
            //这种情况只会复用,只有一个futureTask的时候多个线程来抢只会执行一次
            new Thread(futureTask,"bbb").start();
            //创建两个futureTask
            FutureTask<Integer> futureTask2 = new FutureTask<Integer>(new MyThread());
            new Thread(futureTask2,"ccc").start();

//            使用get获得Callable线程的计算结果,如果没有计算完成就要去强求,会导致阻塞,要放在最后取值
            System.out.println(futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

这里要注意这种方式创建线程的启动方式,由于通过实现Callable接口创建的线程体是Callable类型,而Thread的构造方法的参数是:Thread(Runnable target, String name),是Runnable类型的,这里怎么创建线程并执行呢?通过了解JDK源码,获取线程执行结果是借助了Future,Future有三个作用:

  1. 判断任务是否完成;
  2. 能够中断任务;
  3. 能够获取任务执行结果
    而RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值,能够作为Runnable被线程执行意思就是可以通过new Thread()的方式创建线程,可以看到FutureTask的构造函数有一个为
    在这里插入图片描述
    这个方法便把Callable和Runnable联系起来,我们便可以通过下面
 		FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyThread());
        Thread thread = new Thread(futureTask,"aaa");

的方式创建并执行线程了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值