并发编程(二)——Thread和Runnable

并发编程(二)——Thread和Runnable

一. java中的线程

1.1 创建执行线程

在java中可以通过如下两种方式进行线程的创建

  1. 扩展Thread类并重载run()方法。
  2. 实现Runnable接口,并将该类的对象传递给Thread对象的构造函数。

推荐使用第二种方法来创建执行线程,有以下优势。

  1. Runnable是一个接口,你可以实现其他接口并扩展其他类。对于采用Thread类的方式,你只能扩展这一个类。
  2. 可以通过线程来执行Runnable对象,但也可以通过其他类似执行器的Java并发对象来执行。这样可以更灵活地更改并发应用程序。比如ThreadPoolExecutor(线程池)
  3. 可以通过不同线程使用同一Runnable对象。

线程的启动要使用start()方法创建新的执行线程并且执行Thread类的run()方法。如果直接调用run()方法,那么你将调用常规Java方法而不会创建新的执行线程。

1.2 线程的中止

自然终止:run方法执行完成或者抛出了一个未处理的异常导致线程提前结束。

强行中止:暂停、恢复和停止操作对应在线程Thread的API就是suspend()、resume()和stop()。但是这些API是过期的,也就是不建议使用的。不建议使用的原因主要有:以suspend()方法为例,在调用后,线程不会释放已经占有的资源(比如锁),而是占有着资源进入睡眠状态,这样容易引发死锁问题。同样,stop()方法在终结一个线程时不会保证线程的资源正常释放,通常是没有给予线程完成资源释放工作的机会,因此会导致程序可能工作在不确定状态下。正因为suspend()、resume()和stop()方法带来的副作用,这些方法才被标注为不建议使用的过期方法。

中断:interrupt()/interrupted()/isInterrupted():第一种方法表明你正在请求结束执行某个Thread对象。另外两种方法可用于检查中断状态。这些方法的主要区别在于,调用interrupted()方法时将清除中断标志的值,而isInterrupted()方法不会。

如果一个线程处于了阻塞状态(如线程调用了thread.sleep、thread.join、thread.wait等),则在线程在检查中断标示时如果发现中断标示为true,则会在这些阻塞方法调用处抛出InterruptedException异常,并且在抛出异常后会立即将线程的中断标示位清除,即重新设置为false。

调用interrupt()方法不会结束Thread对象的执行。Thread对象负责检查标志的状态并做出相应的相应。

不建议自定义一个取消标志位来中止线程的运行。因为run方法里有阻塞调用时会无法很快检测到取消标志,线程必须从阻塞调用返回后,才会检查这个取消标志。这种情况下,使用中断会更好,因为

  1. 一般的阻塞方法,如sleep等本身就支持中断的检查。
  2. 检查中断位的状态和检查取消标志位没什么区别,用中断位的状态还可以避免声明取消标志位,减少资源的消耗。

1.3 其他线程的相关方法

yield():当前线程让出CPU占有权,但让出的时间是不可设定的。也不会释放锁资源。注意:并不是每个线程都需要这个锁的,而且执行yield( )的线程不一定就会持有锁,我们完全可以在释放锁后再调用yield方法。

所有执行yield()的线程有可能在进入到就绪状态后会被操作系统再次选中马上又被执行。

join():这个方法将暂停调用线程的执行,直到调用该方法的线程执行结束为止。可以使用该方法等待另一个Thread对象结束。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

sleep():该方法允许你将线程的执行暂停一段时间。它将接收一个long型值作为参数,该值代表你想要Thread对象暂停执行的毫秒数。

setDaemon():该方法可以将当前线程设置为守护线程。当应用程序的所有非守护线程均已结束执行,无论是否有正在运行的守护线程时,守护线程将结束其执行过程。

setPriority():可以更改线程执行的优先级。对于Java虚拟机和线程首选底层操作系统来说,这种优先级是一种提示,而非一种契约。线程的执行顺序并没有保证。通常,较高优先级的线程将在较低优先级的线程之前执行,但是,并不能保证。

1.4 线程的生命周期和状态

线程的可能状态如下。

  1. NEW:Thread对象已经创建,但是还没有开始执行。
  2. RUNNABLE:Thread对象正在Java虚拟机中运行。
  3. BLOCKED :Thread对象正在等待锁定。
  4. WAITING:Thread对象正在等待另一个线程的动作。
  5. TIME_WAITING:Thread对象正在等待另一个线程的操作,但是有时间限制。
  6. THREAD: Thread对象已经完成了执行。


在这里插入图片描述
注意 本文参考书籍《精通java并发编程》和 腾讯课堂享学课堂笔记,只用于个人学习使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值