Day21-1.多线程相关概念 、多线程的创建方式

本文详细介绍了程序、进程和线程的关系,以及并行与并发的区别。通过实例展示了Java中多线程的三种实现方式:继承Thread类、实现Runnable接口以及实现Callable接口。讨论了继承和实现方式的优缺点,并提供了相关代码示例。
摘要由CSDN通过智能技术生成

1 多线程相关的三组概念

1.1 程序和进程

  1. 程序:定义的一些可以用来运行的可执行文件。
    程序不启动,就不会分配内存和系统资源。
  2. 进程:一个正在运行的程序就是进程。
    一个进程运行之后,是有内存的分配和系统资源的分配。

1.2 进程和线程

  1. 进程:正在执行的程序。
  2. 线程:进程中的一条独立的执行单元。
    举例:
        班级:进程
               学生A: 线程
               学生B: 线程
               学生C 线程
    特点:
    (1)进程是有线程组成的
    (2)进程中至少有一条线程
    (3)进程之间互不影响,资源不共享
    (4)一个进程中的线程,资源共享
    (5)如果一个进程中有一条线程,那么该进程就是一个单线程进程
    (6)如果一个进程中有多条线程,那么该进程是一个多线程进程
    比如:在软件中启动一个程序,该程序中就只有一个主方法需要执行,启动该程序之后,就变为一个进程,那么该进程是一个多线程进程
    启动程序之后,JVM调用了主线程main来执行内容
    默认调用一个垃圾回收线程来回收内存中的垃圾数据

1.3 并行和并发

  1. 并行:在某一个时刻,多个进程(线程)同时在执行。
           举例:在9:16:10
                同学A在睡觉
                同学B在学习
                同学C在走神
          问题:如果计算机想要实现并行,需要什么条件?
                需要多个cpu

  2. 并发:在某一个时刻,多个进程(线程)同时启动,同时启动的多个任务会被cpu交替执行。
           要求:同学A在某一个时刻,去学习、去睡觉、去吃饭、去打游戏
           问题:只有一个cpu,使用并发的方式,提高了系统的运行效率还是降低了?
                整体提高了系统的运行效率

2 多线程的第一种实现方式

  1. 方式:继承方式
  2. 步骤:
    (1)自定义一个线程类型
    (2)继承Thread类型
    (3)重写父类中的run方法表示一个具体的任务
    (4)在主方法中创建一个线程类对象
    (5)启动线程
  3. 注意事项:
    (1)新线程的创建和启动,需要借助主线程
    (2)一旦新线程启动之后,两个线程之间互不影响,cpu去谁那谁就执行
    (3)启动线程的方法:start();
  4. 图示:
    在这里插入图片描述

代码

package demos1;
public class Demo01 {
    public static void main(String[] args) {
        //4、创建一个自定义类对象(新线程对象)
        MyThread mt = new MyThread();
        //5、启动新线程
        mt.start();

        for(int i = 1;i <= 1000;i++){
            System.out.println(i + "main线程执行的任务");
        }
    }
}
//1、定义一个类型
//2、需要继承Thread类型
//3、重写父类的run方法
class MyThread extends Thread{
    @Override
    public void run() {
       for(int i = 1;i <= 1000;i++){
           System.out.println("新线程执行的任务:" + i);
       }
    }
}

3 多线程的第二种实现方式

  1. 方式:实现方式
  2. 步骤:
    (1)定义一个类型,表示一个任务类
    (2)实现Runnable接口
    (3)重写接口中的run方法表示需要执行的任务
    (4)在方法中创建一个任务类对象,表示一个具体任务
    (5)创建一个Thread类的线程对象,将任务对象提交给线程对象
    (6)启动线程

代码

package demos1;

public class Demo02 {
    public static void main(String[] args) {
        //4、创建一个自定类对象(任务类)
        MyTask mt = new MyTask();
        //5、创建一个线程,将任务提交给该线程执行
        Thread t = new Thread(mt);
        //6、启动线程,默认执行提交的任务
        t.start();
        
        for(int i = 1;i <= 100;i++){
            System.out.println(i + "主线程执行的任务");
        }
    }
}

//1、定义一个类型
//2、实现一个接口:Runnable
//3、重写接口中的run方法
class MyTask implements  Runnable{
    @Override
    public void run() {
        for(int i = 1;i <= 100;i++){
            System.out.println("新线程需要执行的任务:" + i);
        }
    }
}

4 继承的方式和实现的方式区别

  1. 程序的复杂度:
    继承的方式比较简单,直接创建一个线程对象启动即可
    实现的方式稍微复杂,创建一个任务对象之后,需要再创建一个线程对象,再将任务提交给线程,最后启动。
  2. 程序的灵活性:
    继承的方式灵活性弱:线程类创建的对象只能执行类中定义好的任务,是固定不变的
    实现的方式灵活性强:在创建一个任务对象之后,这个任务对象可以提交给不同的线程 执行;在创建一个线程之后,可以接收不同的任务执行
  3. 程序的扩展性:
    继承的方式,不能再继承其他父类,扩展性弱
    实现的方式,可以继续继承其他父类,扩展性强

5 多线程的第三种创建方式

  1. 实现Callable接口
  2. 步骤:
    (1)定义一个类实现Callable接口
    (2)在类中重写call()方法
    (3)创建自定义类的对象
    (4)创建Future的实现类FutureTask对象,把自定义类对象作为构造方法的参数传递
    (5)创建Thread类的对象,把FutureTask对象作为构造方法的参数传递
    (6)启动线程
    (7)再调用get方法,就可以获取线程结束之后的结果。
  3. 和前两种定义的区别:
    实现的call方法是可以定义返回值

代码

package demos1;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Demo03 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //4、创建一个人物类对象
        MyCallable mc = new MyCallable();
        //5、将创建的任务对象进行包装
        FutureTask<String> fu = new FutureTask<String>(mc);
        //6、将包装之后的任务,提交给线程执行
        Thread t = new Thread(fu);
        //7、启动线程
        t.start();
        //8、获取任务执行之后的返回值
        //   获取的结果要在线程启动之后执行
        String str = fu.get();
        System.out.println(str);
    }
}
//1、定义一个类型表示一个任务类
//2、实现接口:Callable接口
//3、重写接口中的方法,该方法表示需要执行的任务
class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        for(int i = 1;i <= 100;i++){
            System.out.println("我已经向我的女神表白了" + i + "次");
        }
        return "恭喜你,女神同意了!";
    }
}
匿名内部类实现多线程
package demos1;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Demo04 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //3、使用匿名内部类创建一个带着返回值的任务对象
        Callable<String> call = new Callable<String>() {
            @Override
            public String call() throws Exception {
                System.out.println("这是新线程需要执行的任务");
                return "新线程执行结束了";
            }
        };
        FutureTask<String> fu = new FutureTask<>(call);
        Thread t = new Thread(fu);
        t.start();
        System.out.println(fu.get());
    }

    private static void test02() {
        //2、使用匿名内部类创建一个任务对象
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("新线程需要执行的任务");
            }
        };
        Thread t = new Thread(r);
        t.start();
    }

    private static void test01() {
        //1、使用匿名内部类的方式代替第一种写法
        Thread t = new Thread(){
            @Override
            public void run(){
                System.out.println("新线程需要执行的任务");
            }
        };
        t.start();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值