Java 多线程

本文详细介绍了Java中的多线程概念,包括进程、线程、线程的创建(通过继承Thread和实现Runnable)以及线程安全问题。讲解了线程同步的关键字synchronized以及线程池的优势和使用,强调了线程池如何提高代码复用性和响应速度。
摘要由CSDN通过智能技术生成

多线程

一,多线程的概念

进程:正在运行的程序

线程:线程是进程中的一条执行路径(执行单元)

多线程程序:可以开启多条线程的程序

多线程的好处:让程序中的多个任务可以并发执行

CPU执行权的分配方式:

  1. 分时调度:CPU平均分配CPU的执行权

  2. 抢占式调度:任务抢夺CPU的执行权(随机性),Java中的多线程就是采用这种方式的

注:只有主函数的Java程序也有两条线程:主函数所在的主线程、垃圾回收器所在的垃圾回收线程

二,创建线程的方式

方式一:继承Thread

步骤:

  1. 定义一个类继承Thread

  2. 重写Thread类的run方法

    注:run方法中的功能就是多线程中要并发执行的任务

  3. 创建子类对象

  4. 调用Thread类中的start方法,来启动线程

    注:

    1. start方法的作用开启线程调用重写后的run方法

    2. 同一个线程对象只能开启一次,否则会发生IllegalThreadStateException不合法的线程状态异常

    3. 只有程序中的所有线程全部执行完毕,JVM才会结束

方式二:实现Runnable

步骤:

  1. 定义一个类实现Runnable

  2. 重写run方法

  3. 创建实现类的对象

  4. 创建Thread类的对象,并将Runnable实现类的对象作为参数传入到构造函数中

  5. 调用Thread的start方法启动线程

以上两种方式都可以使用匿名内部类来实现:

new Thread(){
 @Override
 public void run() {
     for(;;){
         try {
             Thread.sleep(1);
         } catch (InterruptedException e) {
         }
         System.out.println("张三说:"+strs[r.nextInt(strs.length)]);
     }
 }
}.start();
​
new Thread(new Runnable(){
 @Override
 public void run() {
     for(;;){
         try {
             Thread.sleep(1);
         } catch (InterruptedException e) {
         }
         System.out.println("李四说:"+strs[r.nextInt(strs.length)]);
     }
 }
}).start();

三,线程安全问题

什么是线程安全的:

多个线程操作同一共享数据,最终的结果与单线程操作这一数据的结果一致,就称为线程安全

线程安全问题出现的原因:多个线程操作同一共享数据

解决办法:使用同步技术

同步的关键字:synchronized

  1. 同步代码块

    格式:将存在线程安全问题的代码包裹在同步代码块中

    public void run(){
        synchronized(对象){
            存在线程安全问题的代码
        }
    }

注:同步代码块中的对象称为锁对象,这个对象的类型是任意的,但是要保证这个对象是唯一的

  1. 同步函数

    格式:将存在线程安全问题的代码封装在单独的方法中

    public synchronized 返回类型 方法名(参数){
        存在线程安全问题的代码
    }

注:

  1. 在实现Runnable的方式中,使用同步函数也有锁对象,锁对象是this

  2. 在继承Thread的方式中,使用同步函数是无效的,因为每个线程对象都有各自的this作为锁,此时需要使用静态同步函数,静态同步函数中的锁对象是类名.class

同步技术的原理:

  1. 所有线程共同抢夺CPU的执行权,谁抢到了谁就判断锁是否存在,如果锁存在则获取锁并进入同步代码块中,如果锁不存在则处于阻塞状态

  2. 其他没有抢到CPU执行权的线程会处于阻塞状态,等待抢夺到锁对象的线程执行完毕

  3. 抢夺到锁对象的线程在执行完同步中的所有代码后,会执行释放锁的动作。

四,线程池

概念:线程池的本质就是一个容器,在该容器中存放着若干个线程对象,当有任务需要使用线程时,直接从池中获取线程对象而不再额外创建,当任务执行完毕后,会将使用完的线程对象归还到池中。

线程池的好处:

  1. 提高了代码的复用性。每个线程对象在使用完毕后都会归还到池中,都可以复用。

  2. 提高了程序的响应速度,减少了线程的创建和销毁的次数

  3. 提高了对线程的管理

使用线程池要使用线程池的核心类Executors,它是线程池的工厂类,用于创建线程池

Executors类中提供了生产线程池的静态方法newFixedThreadPool(int nThreads),用于创建一个固定数量的线程对象的线程池,这个方法会返回一个用于开启线程的对象ExecutorService

ExecutorService中提供了submit(Runnable r),调用此方法会从池中获取线程对象并开启线程执行参数Runnable实现类中重写的run方法。

注:即使线程对象已经全部归还,线程池仍然处于开启状态,因为线程池在等待可能还有其他任务需要使用到池中的线程对象。我们可以通过调用shutdown()来手动关闭线程池,一旦线程池关闭了,就不能再从池中获取线程对象并使用,否则会发生RejectedExecutionException

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值