Java创建多线程的几种方式详解

进程与线程

简单介绍下基础概念
进程:在内存中执行的应用程序
线程:进程中最小的执行单元,作用是负责当前进程中程序的运行。一个进程中至少有一个线程,一个进程还可以有多个线程,这样的应用程序就称之为多线程程序

下面介绍下创建多线程的几种方式

一、通过继承Thread类来实现

  1. 定义一个类,继承Thread
  2. 重写run方法,在run方法中设置线程任务(所谓的线程任务指的是此线程要干的具体的事儿,具体执行的代码)
public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("我的线程执行了"+i);
        }
    }
}
  1. 创建自定义线程类的对象
  2. 调用Thread中的start方法,开启线程,jvm自动调用run方法
public class Test {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();//创建线程对象
        //调用start方法,开启线程,jvm自动调用run方法
        t1.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("main线程执行了"+i);
        }
    }
}

二、实现Runnable接口

  1. 创建类,实现Runnable接口
  2. 重写run方法,设置线程任务
public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"执行了"+i);
        }
    }
}
  1. 利用Thread类的构造方法:Thread(Runnable target),创建Thread对象(线程对象),将自定义的类当参数传递到Thread构造中,这一步是让我们自己定义的类成为一个真正的线程类对象
  2. 调用Thread中的start方法,开启线程,jvm自动调用run方法
public class Test {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread t1 = new Thread(myRunnable); //Thread(Runnable target)
        t1.start();//调用Thread中的start方法,开启线程
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"执行了"+i);
        }
    }
}

实现Runnable接口的基础上通过匿名内部类创建多线程

Thread(Runnable target, String name) :name指的是给线程设置名字

public class Test {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName()+"执行了"+i);
                }
            }
        },"哈哈").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName()+"执行了"+i);
                }
            }
        },"你好").start();
    }
}

执行结果如下
在这里插入图片描述

继承Thread类和实现Runnable接口两种实现多线程的方式区别

  1. 继承Thread类方式,只支持单继承,有继承的局限性
  2. 实现Runnable接口方式:没有继承的局限性,可以解决需要继承其它类的需求
MyThread extends 其它类 implements Runnable

三、实现Callable接口

Callable是一个接口,类似于Runnable,其中的方法call() 类似于Runnable接口的run()方法是用来设置线程任务的
call()和run()的区别:call()方法有返回值,而且异常可以throws。run()方法没有返回值,而且有异常不可以throws。

获取call()方法的返回值

FutureTask 实现了一个接口:Future
FutureTask中有一个方法get() 用来获取call方法的返回值。

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"执行了"+i);
        }
        return "call方法返回值";
    }
}
public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyCallable myCallable = new MyCallable();
        FutureTask<String> futureTask = new FutureTask<>(myCallable);
        Thread t1 = new Thread(futureTask);//创建Thread对象-> Thread(Runnable target)
        t1.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("main线程执行了"+i);
        }
        System.out.println(futureTask.get());//调用get方法获取call方法返回值
    }
}

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

四、线程池的方式创建多线程

线程池(ThreadPool)是一种基于池化思想管理和使用线程的机制:它是将多个线程预先存储在一个“池子”内,当有任务出现时可以避免重新创建和销毁线程所带来性能开销,只需要从“池子”内取出相应的线程执行对应的任务即可。解决了之前每来一个线程任务,就需要创建一个线程对象去执行,用完还要销毁线程对象。线程任务多了,就需要频繁创建线程对象和销毁线程对象耗费内存资源多的问题。

  1. 创建获取线程池对象用Executors中的静态方法,其中的参数nThreads指定了线程池中最多创建的线程对象条数。返回值ExecutorService 是线程池,用来管理线程对象。
static ExecutorService newFixedThreadPool(int nThreads)  
  1. ExecutorService中的submit方法用于执行线程任务。返回值用Future接收。

  2. void shutdown() 有序关闭线程池,其中先前提交的任务将被执行,但不会接受任何新任务。

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "call方法返回值";
    }
}
public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService es = Executors.newFixedThreadPool(2);
        Future<String> future = es.submit(new MyCallable());
        System.out.println(future.get());
        es.shutdown(); //有序关闭线程池
    }
}

执行结果如下,如果注释掉了es.shutdown()可以看到程序并没有结束,线程池等的新的线程任务到来。
在这里插入图片描述
具体可以看看这篇文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值