Java线程

本文深入讲解Java中的线程概念,包括单线程与多线程的区别、线程的启动方式及终止条件、线程间的互斥与协作机制等。通过具体示例说明如何使用Thread类和Runnable接口创建线程,探讨了线程同步、暂停和控制的基本方法。

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

1.2 何谓线程

1.2.1 单线程程序

  1. 在单线程程序中,"在某一时间点执行的处理"只有一个,因为 “正在执行程序的主体” 只有一个。
  2. Java程序执行时,至少会有一个线程在运行,即主线程

1.2.2. 多线程程序

  1. 启动新线程时调用的是 start 方法,而不是 run 方法。当然 run 方法是可以调用的,但调用它不会启动新的线程。
  2. 调用 start 方法后,程序会在后台启动新的线程,然后,由这个新线程调用 run 方法
  3. 输出结果显示,多线程情况下输出不一定按照代码顺序。
  4. 顺序、并行与并发:
  • 顺序(sequential)用于表示多个操作“依次处理”。比如把十个操作交给一个人处理时,这个人要一个一个地按顺序来处理。
  • 并行(parallel)用于表示多个操作“同时处理”。比如十个操作分给两个人处理时,这两个人就会并行来处理。
  • 并发(concurrent)相对于顺序和并行来说比较抽象,用于表示 “将一个操作分割成多个部分并且允许无序处理”。比如将十个操作分成相对独立的两类,这样便能够开始并发处理了。如果一个人来处理,这个人就是顺序处理分开的并发操作,而如果是两个人,这两个人就可以并行处理同一个操作。

1.3 线程的启动

1.3.1 启动线程的方法

  1. 利用Thread类的子类的实例启动线程。
  • 创建子类的实例并调用 start 方法
MyThread t = new MyThread();
t.start();
  1. 利用Runnable接口的实现类的实例启动线程。
  • 创建接口实现类的实例,把它作为参数传给Thread的构造函数
Runnable r = new MyThread();
Thread t = new Thread(r);
t.start();

1.3.2 程序的终止

Java程序的终止是指除守护线程(Daemon Thread)以外的线程全部终止。守护线程是执行后台作业的线程。我们可以通过setDaemon方法把线程设置为守护线程。

1.3.3 Thread类和Runnable接口

Thread类本身还实现了Runnable接口,并且持有run方法,但Thread类的run方法是去调用子类的run方法

1.4 线程的暂停

1.4.1 sleep方法的调用

  1. sleep方法的调用放在了try…catch中,这是因为,sleep方法有可能会抛出 InterruptedException 异常。
  2. 如果要中途唤醒被 Thread.sleep休眠的线程,则可以使用interrupt方法。

1.5 线程的互斥处理

1.5.1 synchronized方法

  1. 如果声明一个方法时,在前面加上关键字synchronized,那么这个方法就只能由一个线程运行。只能由一个线程运行是每次只能由一个线程运行的意思,并不是说仅能让某一特定线程运行。
  2. 如果有一个线程正在运行某个实例中的某个synchronized方法,则其他线程就无法运行该实例的所有synchronized方法,但非synchronized方法可以同时运行。
  3. 每个实例拥有一个独立的锁。因此,并不是说某一个实例中的synchronized方法正在执行中,其他实例中的synchronized方法就不可以运行了。

1.5.2 锁和监视

  1. 线程的互斥机制称为监视(monitor)。另外,获取锁有时也叫作“拥有(own)监视”或
    “持有(hold)锁”。
  2. 当前线程是否已获取某一对象的锁可以通过Thread.holdsLock方法来确认。当前线程已获取对象obj的锁时,可使用assert来像下面这样表示出来。
    assert Thread.holdsLock (obj);
  3. synchronized 实例方法是使用 this 的锁来互斥,synchronized 静态方法是使用该类的类对象的锁来互斥

1.6 线程的协作

1.6.1 线程控制方法

Java提供了用于执行线程控制的wait方法、notify方法和notifyAll方法。wait是让线程等待的方法,而notify和notifyAll是唤醒等待中的线程的方法。

1.6.2 等待队列

  1. 所有实例都拥有一个等待队列,它是在实例的wait方法执行后停止操作的线程的队列。打个比方来说,就是为每个实例准备的线程休息室。
  2. 在执行wait方法后,线程便会暂停操作,进入等待队列这个休息室。除非发生下列某一情况,否则线程会一直在等待队列中休眠。当下列任意一种情况发生时,线程便会退出等待队列:
  • 有其他线程的 notify 方法来唤醒线程
  • 有其他线程的 notifyAll 方法来唤醒线程
  • 有其他线程的 interrupt 方法来唤醒线程
  • wait方法超时

1.6.3 wait、notify、notifyAll

  1. 若要执行 wait、notify 和 notifyAll 方法,线程必须持有锁,否则会抛出 illegalMonitorstateException。但如果线程进入等待队列,便会释放其实例的锁。
  2. 假如在执行notify方法时,正在等待队列中等待的线程不止一个,对于 “这时该如何来选择线程” 这个问题规范中并没有作出规定。究竟是选择最先wait的线程,还是随机选择,或者采用其他方法要取决于Java平台运行环境。
  3. notify 方法仅唤醒一个线程,而 notifyAll 则唤醒所有线程,这是两者之间唯一的区别。
  4. wait、notify 和 notifyAll 都是 Object 类的方法,而非 Thread 独有。

线程状态迁移图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值