线程的基本操作-状态、初始化

 

一、线程的状态:

 

线程有如图6种状态,是从JDK源码中截的图,有很详细的注释。NEW   RUNNABLE  BLOCKED  WAITING  TIMED_WAITING  TERMINATED。

1. New(新建)

    当用new操作符创建一个新线程时,如 new Thread(r), 该线程还没有开始运行。这意味着它的状态是new。

    当一个线程处在new状态,程序还没有开始运行线程中的代码。在线程运行之前还有一些基础工作要做。

2. Runnable(可运行)

   一旦调用start()方法,线程就处于runnable状态。可以可运行的线程可能正在运行也可能没有运行,这取决于操作系统给线程提供运行的时间(这就是为什么这个状态成为可运行而不是运行)

   事实上,运行中的线程被中断,目的是为了让他们线程获得运行机会。线程调度的细节依赖于操作系统提供的服务。抢占式调度系统给每一个可运行线程一个时间片来执行任务。当时间片用完,操作系统剥夺该线程的运行权,并给另一个线程可运行机会。当选择下一个线程时,操作系统考虑线程的优先级。

3. Blocked(被阻塞)

|

4. Waiting(等待)

|

5.Timed Waiting(计时等待)

   当线程处于被阻塞或等待状态时,它暂时不活动。它不运行任何代码且消耗最少的资源。直到线程调度器重新激活它。细节取决于它是怎样达到非活动状态的。

   * 当一个线程试图获取一个内部的对象锁(而不是java.util.concurrent库里的锁), 而该锁被其他线程持有,则该线程进入阻塞状态。当其他线程释放该锁,并且线程调度器允许本线程持有它的时候,该线程将变成非阻塞状态。

   * 当线程通知另一个线程通知调度器一个条件时,它自己进入等待状态。在调用Object.wait方法或Thread.join方法,或者是等待java.util.concurrent库中的Lock或Condition时,就会出现这种情况。实际上,被阻塞状态与被等待状态是有很大不同的。

   * 有几个方法有一个超时参数。调用它们导致线程进入计时等待(timed waiting)状态。这一状态将一直保持到超时期满或者接收到适当的通知。带有超时参数的方法有Thread.sleep和Object.wait, Thrad.join, Lock.tryLock以及Condition.await的计时版。

6. Terminated(被终止)

   线程因如下两个原因之一而被终止:

   1) 因为run方法正常退出而自然死亡

   2) 因为一个没有捕获的异常终止了run方法二意外死亡

 

二、线程初始化

线程初始化常用2种方式,继承Thread类,实现Runnable接口

 1 public class Main implements Runnable {
 2 
 3     public static void main(String[] args) {
 4         // write your code here
 5         Thread t1 = new Thread(new Main());
 6         Thread t2 = new Thread() {
 7             @Override
 8             public void run() {
 9                 System.out.println("I'm Thread t2" + Thread.currentThread());
10             }
11         };
12         Thread t3 = new Thread(new Main());
13         System.out.println("主线程" + Thread.currentThread());
14         System.out.println("==============开始验证start run的区别=================");
15         t1.start();
16         t1.run();
17         System.out.println("==============完成验证start run的区别=================");
18 //
19 //        System.out.println("==============调起一个线程,继承Thread类=================");
20 //        t2.start();
21 //        System.out.println("==============调起一个线程,继承Thread类=================");
22 //
23 //        System.out.println("==============调起一个线程,实现Runnable接口,重写run()方法=================");
24 //        t3.start();
25 //        System.out.println("==============调起一个线程,实现Runnable接口,重写run()方法=================");
26     }
27 
28     @Override
29     public void run() {
30         System.out.println("I'm Thread Main" + Thread.currentThread());
31     }
32 }
2种实现方式

t1的构建方式就是是实现Runnable接口,通过Thread的构造方法,将一个实现了Runnable接口的实例对象传入,就可以调用该线程的run方法了。

进入到Runnable接口的源码中会发现,里面其实就一个run的抽象方法,但是配合Thread的构造方法,可以构造出Thread对象,相辅相成。

实际上里面还有很多构造方法,给注入的线程对象给定一个name,传入一个线程组等等。

 

 

 Runnable接口 Thread类对应的构造方法
 

这是Thread类的run方法,执行目标对象的run方法

 

 tips:

1、关于Thread.run()和Thread.start()的问题

两者都可以执行对象的run方法体中对象的代码,但是,start()会创建一个新的线程并让这个线程执行run()方法,而类.run()开启的线程,貌似是新线程,实际上是串行执行run()中的代码。

如图,其实直接调用的run方法还是在main主线程中,而start的才是一个真正的新线程。

2、常用的话,还是实现Runnable接口,毕竟Java单继承,只能认一个干爹,继承Thread太浪费了。

 

转载于:https://www.cnblogs.com/starmoon1994/p/7469697.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值