Java——多线程

本文围绕Java多线程展开,介绍了多线程的概念,即进程内的多个执行路径。阐述了其作用是提高程序使用率,分析了优缺点。还详细讲解了三种创建方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并对三种方式进行了比较。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是多线程?

线程是指进程中的一个执行流程,一个进程中可以运行1-n个线程,也可以说是在同一个进程内又可以执行多个任务,而每一个任务我们就可以看成一个线程。是程序的执行单元,执行路径。是程序使用CPU的最基本的单位;如果程序只有一条执行路径,那么该程序就是单线程,如果程序有多条执行路径,那么该程序就多线程。

多线程的作用?

多线程不是为了提高程序的执行速度,而是为了提高程序的使用率。多线程的执行都是为了抢占CPU的使用率。不能保证多线程会在什么时候优先抢到使用权,所以线程的执行具有随机性。

多线程的优点?

充分利用硬件资源。由于线程是CPU的基本调度单位,所以如果是单线程,那么最多只能同时在一个处理器上运行,意味着其他的CPU资源都将被浪费。而多线程可以同时在多个处理器上运行,只要各个线程间的通信设计正确,那么多线程将能充分利用处理器的资源。

多线程程序能将代码量巨大,复杂的程序分成一个个简单的功能模块,每块实现复杂程序的一部分单一功能,这将会使得程序的建模,测试更加方便,结构更加清晰,更加优雅

为了避免阻塞,单线程应用必须使用非阻塞I/O,这样的I/O复杂性远远高于同步I/O,并且容易出错。

多线程的缺点?

由于统一进程下的多个线程是共享同样的地址空间和数据的,又由于线程执行顺序是不可预知性,一个线程可能会修改其他线程正在使用的变量,这一方面是给数据共享带来了便利;另一方面,如果处理不当,会产生脏读,幻读等问题,好在Java提供了一系列的同步机制来帮助解决这一问题,例如内置锁。

多线程的创建方式?

继承Thread类

创建一个类,继承Thread类,该类具备多线程的特征。重写Thread类的run方法,在run方法当中定义线程任务。Run()方法体又叫做线程执行体。

创建Thread类的子类的实例,即创建了线程对象。通过调用该对象的start方法开启一条新线程,调用start方法之后Java虚拟机会自动调用该线程的run方法。

为什么要继承Thread类?为社么不直接创建Thread对象?

new Thread类得到一个线程对象是没有任何问题的,调用start()开启了一个新的线程,此时JVM会自动去调run方法,但是run方法当中没有任何的内容;

所以需要定义一个类,继承Thread类,此时就可以重写run方法,把线程任务定义在run方法当中即可。

实现Runnable接口方式

创建一个类A:实现Runnable接口,并重写run方法,在run方法内定义线程任务

创建Runnable接口实现类的实例并且作为一个target传递给Thread类的构造器创建一个Thread类对象,此时Runnable接口和Thread类就具有联系,而该Thread对象才是真正的线程对象。

使用Thread对象的start方法开启一个新的线程

当类实现Runnable接口时,只能用Thread.currentThread()方法获取当前线程对象

实现Callable接口

 

  1. 创建一个类A实现Callable接口,重写call方法定义线程任务。
  2. 新建FutureTask类,传入类A,该类可以获取返回值。
  3. 新建Thread类传入FutureTask对象,使用start方法开启线程。
  4. 使用FutureTask类的get方法获取返回值。

 

Java5使用Callable和Future创建线程,一般和ExecutorService连用。
  和Runnable接口不一样,Callable接口提供了一个call()方法作为线程执行体,call()方法比run()方法功能要强大:

  1. call()方法可以有返回值
  2. call()方法可以声明抛出异常

  Java5提供了Future接口来代表Callable接口里call()方法的返回值,并且为Future接口提供了一个实现类FutureTask,这个实现类既实现了Future接口,还实现了Runnable接口,因此可以作为Thread类的target。在Future接口里定义了几个公共方法来控制它关联的Callable任务

三种方式实现比较

     继承Thread类

  1. 实现简单,直接继承Thread即可。并且在run()方法内获取当前线程直接使用this
    就可以了,无须使用Thread.currentThread() 方法;
  2. java当中的继承只能是单继承,一个类只能继承一个直接父类。如果一个类继承了Thread类,就不能有其他的父类。
  3. 创建的对象,即封装了线程任务,又封装了线程对象的特点(线程对象),不同的东西封装到了一个对象之中,不符合java面向对象的特点

    实现Runnable接口

  1. run()方法内获取当前线程不能使用使用this,必须使用Thread.currentThread() 方法;
  2. 将线程任务单独的封装到一个接口实现类当中,将线程任务和线程对象进行了分离:Runnable接口实现类当中定义线程任务,Thread类封装了线程对象,将不同的功能封装到不同的对象之中,这种思想更加的符合面向对象的特点。
  3. 避免了单继承带来的局限性。
  4. 适合多条线程处理同一个资源的情况,很容易的实现资源共享。需要多个线程完成一个任务时,比如:多个线程共同卖100张票,他们需要共享100张票这个资源。                                   实现Callable接口
  • 具有实现Runnable接口的特点,同时还能获取返回值,并且可以抛出异常
  •  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值