线程(Thread)

1.了解多线程

1.1 概念

  • 进程是系统分配资源的最小单位,线程是系统调度的最小单位
  • 一个进程内的线程之间是可以共享资源的。
  • 每个进程至少有一个线程存在,即主线程。
  • 线程创建比进程创建更轻量级。(线程是轻量级进程)
    在这里插入图片描述
    Java自己的线程:
    在这里插入图片描述
    JVM中的线程不一定就是OS中的线程,但表现出来的特性是相似的。
    对于Java程序员,不需要关心操作系统中的线程。

1.2 观察线程

1.2.1 示例

public class ThreadDemo1 {
    private static class MyThread extends Thread {
        @Override
        public void run() {
            while (true) {
                System.out.println("我在 method2 中打印");
                // 进程会暂停运行 1 秒
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void method2() {
        Thread thread = new MyThread();
        thread.start();
    }

    public static void main(String[] args) throws InterruptedException {
        /*
        //method1死循环
        method1();
        */
        
        // 两个死循环可以同时开始执行,没有一个卡住另一个的情况
        method2();
        while (true) {
            System.out.println("我在 main 中打印");
            // 进程会暂停运行 1 秒
            Thread.sleep(1000);
        }
    }

    private static void method1() throws InterruptedException {
        while (true) {
            System.out.println("我在 method1 中打印");
            // 进程会暂停运行 1 秒
            Thread.sleep(1000);
        }
    }
}

1.调用method1(),死循环
在这里插入图片描述
2.调用method2(),两个死循环可以同时开始执行,没有一个卡住另一个的情况
在这里插入图片描述

1.2.2 使用jconsole观察线程

前提:运行程序

方法一:直接双击打开
在这里插入图片描述
在这里插入图片描述
方法二:在IDEA的jconsole命令

1.打开Terminal
在这里插入图片描述
2.运行jconsole命令
在这里插入图片描述
3.观察线程
在这里插入图片描述

1.2.3 线程阻塞观察

  1. mian线程处于阻塞状态
    在这里插入图片描述

  2. 子线程处于阻塞状态
    在这里插入图片描述

  3. main线程和子线程均处于阻塞状态
    在这里插入图片描述

  4. 线程执行顺序
    在这里插入图片描述

1.3 多线程的优势

一、什么时候使用多线程?
(1)需要同时执行多个任务,当每个任务量都比较大时,可以使用多线程提高效率。
(2)当前线程执行阻塞式代码时,需要同时执行其他代码,可以使用多线程达到不阻塞执行其他代码的目的。

二、使用多线程的优势?
(1) 某些场景下,建模简单(代码好写)。
(2) 某些场景下,增加运行速度。

public class ThreadDemo2 {
    private static final long COUNT = 10_0000_0000;

    public static void main(String[] args) throws InterruptedException {
        serial();     // 串行
        concurrent();   // 并发
    }

    private static class CalcThread extends Thread {
        @Override
        public void run() {
            int n = 0;
            for (long i = 0; i < COUNT; i++) {
                n++;
            }
        }
    }

    private static void concurrent() throws InterruptedException {
        long begin = System.nanoTime();

        Thread thread1 = new CalcThread();
        thread1.start();
        Thread thread2 = new CalcThread();
        thread2.start();

        int a = 0;
        for (long i = 0; i < COUNT; i++) {
            a++;
        }

        thread1.join();
        thread2.join();

        long end = System.nanoTime();
        double s = (end - begin) * 1.0 / 1000 / 1000 / 1000;
        System.out.printf("并发模式: 耗时: %.4f%n", s);
    }

    private static void serial() {
        long begin = System.nanoTime();

        int a = 0;
        for (long i = 0; i < COUNT; i++) {
            a++;
        }
        int b = 0;
        for (long i = 0; i < COUNT; i++) {
            b++;
        }
        int c = 0;
        for (long i = 0; i < COUNT; i++) {
            c++;
        }

        long end = System.nanoTime();
        double s = (end - begin) * 1.0 / 1000 / 1000 / 1000;
        System.out.printf("串行模式: 耗时: %.4f%n", s);
    }
}

运行结果:
在这里插入图片描述
注意多线程不一定都比单线程快

eg:数据量是100000时,单线程更快一点,运行结果如下
在这里插入图片描述
三、多线程的效率问题

(1)运行单个线程的任务量
          任务量越小,相对线程创建及申请系统调度的时间来说,不是很划算。
(2)运行的线程数量
          线程数与系统资源(包括CPU核数、内存大小等等)相关,在当前系统可用资源的条件下,多线程数量有一定阈值。如果单个任务量比较多,使用多线程提高效率(通过增加线程数提高效率时,达到阈值后,效率下降)。

1.4 创建线程

Thread类作用:线程的描述类。

每一个线程都有一个Thread对象与之一一关联。

1.4.1 创建线程_继承Thread类

可以通过继承 Thread 来创建一个线程类,该方法的好处是 this 代表的就是当前线程,不需要通过 Thread.currentThread() 来获取当前线程的引用

class MyThread extends Thread {
    @Override
    public void run() {
    System.out.println("这里是线程运行的代码");
    }
}
 MyThread t = new MyThread();
 t.start(); // 线程开始运行

1.4.2 创建线程_实现 Runnable 接口

通过实现 Runnable 接口,并且调用 Thread 的构造方法时将 Runnable 对象作为 target 参数传入来创建线程对象。

该方法的好处是可以规避类的单继承的限制;但需要通过 Thread.currentThread() 来获取当前线程的引用

class MyRunnable implements Runnable { // Runnable 为线程的任务描述
@Override
   public void run() {
   System.out.println(Thread.currentThread().getName() + "这里是线程运行的代码");
   }
}
 Thread t = new Thread(new MyRunnable());
 t.start(); // 线程开始运行

2.Thread 类及常见方法

https://editor.csdn.net/md/?articleId=104105959

3.线程的六种状态和状态转移图

https://editor.csdn.net/md/?articleId=102922752#31__1

4.线程安不安全?

https://editor.csdn.net/md/?articleId=104126766

5.java中保证线程安全的机制

https://blog.csdn.net/qq_43361209/article/details/103000818

6.多线程案例

1.阻塞式队列—生产者消费者模式
https://blog.csdn.net/qq_43361209/article/details/104155767
2.单例模式
https://blog.csdn.net/qq_43361209/article/details/104155700
3.定时器
https://blog.csdn.net/qq_43361209/article/details/104158322
4.线程池
https://blog.csdn.net/qq_43361209/article/details/104160774

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值