【Java进阶】多线程&高并发(一)<线程概述>

一、线程相关概念

1. 进程

  • 进程(process)是计算机中的程序关于某数据集合上的一次运行活动,是操作系统进行资源分配与调度的基本单位
  • 进程可以简单理解为正在操作系统中运行的一个程序

2. 线程

  • 线程(thread)是进程的一个执行单元
  • 一个线程就是进程中一个单一顺序的控制流,是进程的一个执行分支

3. 进程和线程区别

  • 进程是线程的容器,一个进程至少有一个线程,一个进程中可以有多个线程
  • 在操作系统中是以进程为单位分配资源的,如:虚拟存储空间、文件描述符等
  • 每个线程都有各自的线程栈,自己的寄存器环境,自己的线程本地存储

4. 主线程和子线程

  • JVM启动时会创建一个主线程,该主线程负责执行main()方法,主线程就是运行main()方法的线程
  • Java中的线程不是孤立的,线程之间存在一些联系,如果在A线程中创建了B线程,称B线程是A线程的子线程,相应的A线程就是B线程的父线程

5. 串行、并发和并行

在这里插入图片描述

  • 并发可以提高事物的处理效率,即一段时间内可以处理或者完成更多的事情
  • 并行是一种更为严格、理想的并发
  • 从硬件角度来说,如果单核CPU,一个处理器一次只能执行一个线程的情况下,处理器可以使用时间片轮转技术,可以让CPU快速的在各个线程之间进行切换,对于用户来说,感觉是三个线程在同时执行。如果是多核心CPU,可以为不同的线程分配不同的CPU内核

二、线程的创建与启动

1. 介绍

  • 在Java中,创建一个线程就是创建一个Thread类(子类)的对象(实例)
  • Thread类有两个常用的构造方法:Thread()和Thread(Runnable),对应的创建线程的两种方式,这两种创建线程的方式没有本质的区别
    ① 定义Thread类的子类
    ② 定义一个Runnable接口的实现类

2. 继承Thread类

  • 基本使用
package Thread;

/**
 * 继承Thread类
 *
 * @author swaggyhang
 * @create 2023-06-14 19:51
 */
public class ExtendsThreadDemo {
    public static void main(String[] args) {
        System.out.println("JVM启动main线程,main线程执行main()方法");
        // 3 创建子线程对象
        MyThread thread = new MyThread();

        // 4 启动线程
        thread.start();

        /**
         * 1)调用线程的start()方法来启动线程
         * 2)启动线程的实质就是请求JVM运行相应的程序,这个线程具体在什么时候运行,由线程调度器(Scheduler)决定
         * 3)start()方法调用结束并不意味着子线程运行开始
         * 4)新开启的线程会执行run()方法
         * 5)如果开启了多个线程,start()方法调用的顺序并不一定就是线程启动的顺序
         * 6)多线程运行结果与代码执行顺序或调用顺序无关
         */
        System.out.println("main线程后面其他的代码...");
    }
}

// 1 定义类继承Thread
class MyThread extends Thread {

    // 2 重写Thread类的run()方法
    // run()方法体中的代码就是子线程要执行的任务
    @Override
    public void run() {
        System.out.println("这是子线程打印的内容");
    }
}
  • 多线程运行结果是随机的
package Thread;

/**
 * 多线程运行结果是随机的
 *
 * @author swaggyhang
 * @create 2023-06-14 20:21
 */
public class ThreadRandomDemo {
    public static void main(String[] args) {
        MyThread2 thread2 = new MyThread2();
        thread2.start();    // 开启子线程

        // 当前是main线程
        try {
            for (int i = 0; i < 10; i++) {
                System.out.println("main--:" + i);
                int time = (int) (Math.random() * 1000);
                Thread.sleep(time); // 线程睡眠,单位是毫秒
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class MyThread2 extends Thread {
    @Override
    public void run() {
        try {
            for (int i = 0; i < 10; i++) {
                System.out.println("sub thread:" + i);
                int time = (int) (Math.random() * 1000);
                Thread.sleep(time); // 线程睡眠,单位是毫秒
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

3. 实现Runnable接口

package Thread;

/**
 * 当线程类以及有父类了,就不能用继承Thread类来创建线程,可以使用实现Runnable接口来创建线程
 *
 * @author swaggyhang
 * @create 2023-06-14 20:56
 */
public class ImplementsRunnableDemo {
    public static void main(String[] args) {
        // 3 创建Runnable接口的实现类对象
        MyRunnable runnable = new MyRunnable();
        // 4 创建线程对象
        Thread thread = new Thread(runnable);
        // 5 开启线程
        thread.start();

        // 当前是main线程
        for (int i = 0; i < 10000; i++) {
            System.out.println("main ==> " + i);
        }

        // 有时调用Thread(Runnable)构造方法时,实参也会传递匿名内部类对象
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10000; i++) {
                    System.out.println("sub ----------------> " + i);
                }
            }
        });
        thread2.start();
    }
}

// 1 定义类实现Runnable接口
class MyRunnable implements Runnable {
    // 2 重写Runnable接口中的抽象方法run(),run()方法就是子线程要执行的代码
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            System.out.println("sub thread --> " + i);
        }
    }
}

三、线程的常用方法

1. currentThread()方法

  • Thread.currentThread()方法可以获得当前线程
  • Java中的任何一段代码都是执行在某个线程当中的,执行当前代码的线程就是当前线程
  • 同一段代码可能被不同的线程执行,因此当前线程是相对的
  • Thread.currentThread()方法的返回值是在代码实际运行时候的线程对象
  • 基础使用
package Thread;

/**
 * @author swaggyhang
 * @create 2023-06-14 21:15
 */
public class CurrentThreadDemo {
    public static void main(String[] args) {
        System.out.println("main方法中打印当前线程:" + Thread.currentThread().getName());

        // 创建子线程,调用SubThread1()构造方法,在main线程中调用的,因此构造方法中的当前线程就是main线程
        SubThread1 t1 = new SubThread1();
        t1.start(); // 启动子线程,子线程会调用run()方法,因此run()方法中的当前线程就是Thread-0子线程

        t1.run();   // 在main()方法中直接调用run()方法,没有开启新的线程,因此在run()方法中的当前线程是main线程
    }
}

class SubThread1 extends Thread {
    public SubThread1() {
        System.out.println("构造方法打印当前线程名称:" + Thread.currentThread().getName());
    }

    @Override
    public void run() {
        System.out.println("run方法打印当前线程名称:" + Thread.currentThread().getName());
    }
}
  • 复杂案例
package Thread;

/**
 * @author swaggyhang
 * @create 2023-06-14 21:24
 */
public class CurrentThreadComplexDemo {
    public static void main(String[] args) throws InterruptedException {
        // 创建子线程对象
        SubThread2 t2 = new SubThread2();
        t2.setName("t2");   // 设置线程名称
        t2.start();

        Thread.sleep(500);  // main线程睡眠500毫秒,保证t2线程已经启动

        // Thread(Runnable)构造方法形参是Runnable接口,调用时传递的实参是该接口的实现类对象
        Thread t3 = new Thread(t2);
        t3.start();
    }
}

class SubThread2 extends Thread {
    public SubThread2() {
        System.out.println("构造方法中,Thread.currentThread().getName():" + Thread.currentThread().getName());
        System.out.println("构造方法中,this.getName():" + this.getName());
    }

    @Override
    public void run() {
        System.out.println("run方法中,Thread.currentThread().getName():" + Thread.currentThread().getName());
        System.out.println("run方法中,this.getName():" + this.getName());
    }
}

2. setName()/getName()方法

  • thread.setName(线程名称),设置线程名称
  • thread.getName()返回线程名称
  • 通过设置线程名称,有助于程序调试,提高程序的可读性,建议为每个线程都设置一个能够体现线程功能的名称

3. isAlive()方法

  • thread.isAlive()判断当前线程是否处于活动状态
  • 活动状态就是线程已经启动并且尚未终止
package Thread;

/**
 * 线程的活动状态
 *
 * @author swaggyhang
 * @create 2023-06-14 21:51
 */
public class IsAliveDemo {
    public static void main(String[] args) {
        SubThread3 t3 = new SubThread3();
        System.out.println("begin==,isAlive = " + t3.isAlive());    // false,在启动线程之前
        t3.start();
        System.out.println("end==,isAlive = " + t3.isAlive());  // 结果不一定,打印这一行时,如果t3线程还没结束就返回true,结束了就返回false
    }
}

class SubThread3 extends Thread {
    @Override
    public void run() {
        System.out.println("run方法,isAlive = " + this.isAlive());
    }
}

四、线程的生命周期

五、多线程编程的优势与存在的风险

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java多线程高并发Java中非常重要的概念和技术,它们可以让Java程序更加高效地利用计算机多核CPU的性能,提升程序的并发能力,提高程序的性能和响应速度。 Java多线程机制是基于线程对象的,它允许程序同时执行多个任务,从而提高程序的并发能力。Java中的线程有两种创建方式:继承Thread类和实现Runnable接口。其中继承Thread类是比较简单的一种方式,但是它会限制程序的扩展性和灵活性,因为Java只支持单继承。而实现Runnable接口则更加灵活,因为Java支持多实现。 Java高并发编程主要包括以下几个方面: 1. 线程池技术:线程池技术是Java中非常重要的高并发编程技术,它可以实现线程的复用,减少线程创建和销毁的开销,提高程序的性能和响应速度。 2. 锁机制:Java中的锁机制包括synchronized关键字、ReentrantLock锁、ReadWriteLock读写锁等,它们可以保证多个线程之间的互斥访问,避免数据竞争和线程安全问题。 3. CAS操作:CAS(Compare and Swap)操作是Java中一种非常高效的并发编程技术,它可以实现无锁并发访问,避免线程之间的互斥和阻塞,提高程序的性能和响应速度。 4. 并发集合类:Java中的并发集合类包括ConcurrentHashMap、ConcurrentLinkedQueue、CopyOnWriteArrayList等,它们可以实现线程安全的数据访问和操作,有效地提高程序的并发能力。 总之,Java多线程高并发Java编程中非常重要的概念和技术,掌握这些技术可以让Java程序更加高效地利用计算机多核CPU的性能,提升程序的并发能力,提高程序的性能和响应速度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值