Java多线程——认识线程


一、认识线程(Thread)

1.概念

(1)线程是什么?

线程是程序执行流的最小单元,是进程中的一个实体,是被系统独立调度和分派的基本单位。⼀个线程就是⼀个"执⾏流"。每 个线程之间都可以按照顺序执⾏⾃⼰的代码,多个线程之间"同时"执⾏着多份代码。

举个例子:
一家餐厅要准备一场大型宴会的餐食,既需要烹饪热菜,又要制作精致的甜品,还得准备新鲜的沙拉。​
如果只有主厨一人操刀,不仅任务繁重,而且会耗费大量时间,难以按时完成宴会餐食的准备。为了高效完成任务,主厨邀请了两位帮厨小刘和小赵前来协助。三人分别负责不同的工作:主厨负责烹饪热菜,小刘专注于制作甜品,小赵着手准备沙拉。他们各自在厨房的不同区域同时开工,就像拥有了三个独立的 “执行流”,共同为这场宴会餐食的准备努力,本质上都是在完成同一场宴会的餐饮任务。​
此时,这种情况就好比多线程,将准备宴会餐食这个大任务拆解成不同的小任务,交给不同的 “执行流” 并行执行。因为是主厨组织并统筹整个任务,所以主厨就相当于主线程(MainThread)


(2)为啥要有线程?

⾸先,“并发编程"成为"刚需”。

  • 单核 CPU 的发展遇到了瓶颈。要想提高算力,就需要多核 CPU。而并发编程能更充分利用多核 CPU 资源。
  • 有些任务场景需要 “等待 IO”,为了让等待 IO 的时间能够去做一些其他的工作,也需要用到并发编程。

其次,虽然多进程也能实现并发编程,但是线程比进程更轻量。

  • 创建线程比创建进程更快。
  • 销毁线程比销毁进程更快。
  • 调度线程比调度进程更快。
    线程虽然⽐进程轻量,但是⼈们还不满⾜,于是⼜有了"线程池(ThreadPool)和"协程"

(3)进程和线程的区别

  • 进程是包含线程的。每个进程至少有一个线程存在,即主线程。
  • 进程和进程之间不共享内存空间。同一个进程的线程之间共享同一个内存空间。
  • 进程是系统分配资源的最小单位,线程是系统调度的最小单位。
  • 一个进程挂了一般不会影响到其他进程。但是一个线程挂了,可能把同进程内的其他线程一起带走(整个进程崩溃)。

(4)Java 的线程和操作系统线程的关系

线程是操作系统中的概念。操作系统内核实现了线程这样的机制,并且对用户层提供了一些 API 供用户使用(例如 Linux 的 pthread 库)。
Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进行了进一步的抽象和封装。




二、创建线程

方法1继承Thread类

继承Thread来创建⼀个线程类:

class MyThread extends Thread {
 	@Override
 	public void run() {
 		System.out.println("这⾥是线程运⾏的代码");
 	}
 }

创建MyThread类的实例

MyThread t = new MyThread();

调⽤start⽅法启动线程


 t.start();        // 线程开始运⾏
 

方法2实现Runnable接口

1.实现Runnable接⼝

class MyRunnable implements Runnable {
 	@Override
	 public void run() {
 		System.out.println("这⾥是线程运⾏的代码");
 	}
 }
  1. 创建Thread类实例,调⽤Thread的构造⽅法时将Runnable对象作为target参数.
Thread t = new Thread(new MyRunnable());
  1. 调⽤start⽅法

 t.start();        // 线程开始运⾏
 

对比上面两种方法:

  • 继承 Thread 类,直接使用 this 就表示当前线程对象的引用。
  • 实现 Runnable 接口,this 表示的是 MyRunnable 的引用。需要使用 Thread.currentThread ()。

其他变形

  • 匿名内部类创建 Thread 子类对象
// 使用匿名类创建Thread子类对象
Thread t1 = new Thread() {
    @Override
    public void run() {
        System.out.println("使用匿名类创建Thread子类对象");
    }
};
  • 匿名内部类创建 Runnable 子类对象
// 使用匿名类创建Runnable子类对象
Thread t2 = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("使用匿名类创建Runnable子类对象");
    }
});
  • lambda 表达式创建 Runnable 子类对象
// 使用lambda表达式创建Runnable子类对象
Thread t3 = new Thread(() -> System.out.println("使用匿名类创建Thread子类对象"));
Thread t4 = new Thread(() -> {
    System.out.println("使用匿名类创建Thread子类对象");
});

在这里插入代码片




四、多线程的优势-增加运⾏速度

可以观察多线程在⼀些场合下是可以提⾼程序的整体运⾏效率的。

  • 使用 System.nanoTime () 可以记录当前系统的纳秒级时间戳。
  • serial 串行的完成一系列运算。concurrency 使用两个线程并行的完成同样的运算。
public class ThreadAdvantage {
    // 多线程并不一定就能提高速度,可以观察,count不同,实际的运行效果也是不同的
    private static final long count = 10_0000_0000;
    public static void main(String[] args) throws InterruptedException {
        // 使用并发方式
        concurrency();
        // 使用串行方式
        serial();
    }
    private static void concurrency() throws InterruptedException {
        long begin = System.nanoTime();
        // 利用一个线程计算a的值
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                int a = 0;
                for (int i = 0; i < count; i++) {
                    a--;
                }
            }
        });
        thread.start();
        //主线程内计算b的值
        int b = 0;
        for (int i = 0; i < count; i++) {
            b--;
        }
        //等待thread线程运行结束
        thread.join();
        //统计耗时
        Long end = System.nanoTime();
        double ms = (end - begin) * 1.0 / 1000 / 1000;
        System.out.printf("并发:%f毫秒%n", ms);
    }
    private static void serial() {
        //全部在主线程内计算a、b的值
        Long begin = System.nanoTime();
        int a = 0;
        for (int i = 0; i < count; i++) {
            a--;
        }
        int b = 0;
        for (int i = 0; i < count; i++) {
            b--;
        }
        Long end = System.nanoTime();
        double ms = (end - begin) * 1.0 / 1000 / 1000;
        System.out.printf("串行:%f毫秒%n", ms);
    }
}

多运行几次,可见效率差别之大
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述











评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值