Java多线程最全总结

基本概念

进程

进程是操作系统资源分配的基本单位,操作系统在运行时会为每个进程分配不同的内存区域。进程是程序的一次执行过程:程序运行,加载到内存中,占用了cpu的资源。

线程

线程是cpu调度和执行的基本单位,每个线程拥有独立的运行栈和程序计数器(pc),线程切换的开销比进程小。

同一个进程中的多个线程共享相同的内存单元,线程从同一堆中分配对象,可以访问相同的变量和对象。每个进程都会有一个方法区和堆,多个线程共享同一进程下的方法区和堆。多个线程操作同一个共享数据,这就可能导致线程安全问题。

多线程的优点:提高应用程序的响应效率,可以增强用户体验。提高计算机CPU的利用率。

需要多线程的时机:

  • 需要同时执行多个任务。
  • 需要在后台运行的程序。
  • 实现一些需要等待的任务时,文件读写操作、网络操作等。

创建线程和启动线程

java多线程实现

多线程可以通过Java中的Thread类来体现,线程的主题逻辑是通过Thread对象的run()方法来操作的,把run()方法的主体称为线程体。通过Thread的start()方法来启动这个线程。

创建多线程

继承Thread类

  1. 创建继承于Thread类的子类。
  2. 重写Thread类的run()方法。
  3. 建这个子类的实例对象。
  4. 通过此对象调用start()来启动线程。
    代码:
public class Thread1 extends Thread {

    // 启动线程时会运行run方法中的代码
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            if (i % 3 == 0){
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }

    public static void main(String[] args) {
        Thread1 t1 = new Thread1();
        t1.start();
        Thread1 t2 = new Thread1();
        t2.start();
        System.out.println("main方法");
    }
}

运行结果:

main方法
Thread-0: 0
Thread-1: 0
Thread-1: 3
Thread-0: 3
Thread-0: 6
Thread-1: 6
Thread-0: 9
Thread-1: 9

实现Runnable接口

  1. 创建一个实现Runnable接口的类class1。
  2. 在实现类重写run方法。
  3. 创建类class1的实例对象obj1。
  4. 创建Thread类的对象,将此对象obj1作为构造函数参数。
  5. 调用Thread类的实例对象的start方法。

代码:

public class Thread1 {
    public static void main(String[] args) {
        RunnableThread1 runnableThread01 = new RunnableThread1();
        Thread t1 = new Thread(runnableThread01);
        t1.start();
        Thread t2 = new Thread(runnableThread01);
        t2.start();
        System.out.println("main方法");
    }
}

class RunnableThread1 implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            if (i % 3 == 0) {
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }
}

实现Callable接口

代码省略

三种实现多线程方式的比较

  1. 用实现Runnable接口的方式来实现多线程更加实用。
  2. 继承Thread实现多线程的方式,需要创建多个子类的对象来进行多线程,而实现Runnable接口的实现多线程方式,只需要创建一个实现类的对象,要将这个对象传入Thread类并创建多个Thread类的对象来完成多线程。
  3. 实现Runnable接口的方式更适合处理多个线程有共享数据的情况。
  4. 实现Runnable接口和继承Thread两种方式都需要重写run方法,线程的核心执行逻辑都在run方法中。
  5. 用实现Callable接口的方式功能更强大,相比run方法,可以有返回值,方法可以抛出异常,支持泛型的返回值。

用线程池实现多线程

使用线程池实现多线程减少了创建新线程的时间,可以提高响应速度;可以重复利用线程池中线程,降低资源消耗;便于管理线程。

代码:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class ThreadClass implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            if (i % 3 == 0) {
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }
}

public class Thread1 {
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(2);

        service.execute(new ThreadClass()); //用于实现Runnable的方式
        service.execute(new ThreadClass());
        //service.submit(); 适用于实现Callable的方式
        //关闭线程池
        service.shutdown();
        System.out.println("main方法");
    }
}

结果:

pool-1-thread-2: 0
main方法
pool-1-thread-1: 0
pool-1-thread-2: 3
pool-1-thread-1: 3
pool-1-thread-1: 6
pool-1-thread-2: 6
pool-1-thread-1: 9
pool-1-thread-2: 9

Thread常用方法

  1. start() : 启动线程
  2. run() : 线程核心执行逻辑
  3. yield() : 释放CPU
  4. join() : 阻塞作用,如果在线程a中调用线程b的join(), 此时线程a进入阻塞状态, 直到线程b完全执行完以后, 线程a才结束阻塞状态
  5. sleep(long militime) : 让线程睡眠指定的毫秒数,在指定时间内,线程是阻塞状态
  6. currentThread() : 静态方法, 返回当前代码执行的线程
  7. getName() : 获取当前线程的名字
  8. setName() : 设置当前线程的名字

线程的生命周期

  1. 新建:Thread子类的实例对象被声明并创建时,线程对象处于新建状态。
  2. 就绪:处于新建状态的线程start后,将进入线程队列等待CPU时间片,此时它没分配到CPU资源。
  3. 运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态。
  4. 阻塞:被挂起或执行输入输出操作时,让出CPU并临时中止执行,进入阻塞状态。
  5. 死亡:线程完成了它的全部工作或线程被提前强制中止或出现异常。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值