基础知识

线程状态

根据Thread.State类中的描述,Java中线程有六种状态:NEW,RUNNABLE,WAITING,TERMINATED,BLOCKED。

就绪状态(NEW):当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。

运行状态(RUNNABLE):如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。

阻塞状态:如果一个线程执行了sleep(睡眠)、wait(等待)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:

  • 等待阻塞(WAITING):运行状态中的线程执行 wait() ,join(),park()方法,使线程进入到等待阻塞状态。
  • 同步阻塞(BLOCKED):线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
  • 其他阻塞(TiMED_WAITHIN):通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入运行态。

死亡状态(TERMINATED):一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

值得注意的是,以上状态为JVM线程状态,不反应操作系统线程状态。

                                            线程状态迁移图

线程优先级

每一个 Java 线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。线程优先级是一个正整数,所有创建的线程默认优先级为5(Thread.NORM_PRIORITY),可设置最大优先级为10(Thread.MAX_PRIORITY),最小优先级为1(Thread.MIN_PRIORITY)。在所有得到其他资源并等待处理器资源的线程中,优先级高的线程理论上将被更有可能被优先调度。

守护线程

守护线程意味着不重要的线程(骑士对于公主来说,是守护者,是可有可无的备胎),因而当某进程只有守护线程在执行时,该进程会立即结束运行。    

创建可运行的类

继承Thread类

1.新建类继承Thread类。

2.重写run()方法。该run()方法的方法体就代表了线程需要完成的任务。

3.创建Thread子类的实例。

4.调用线程对象的start()方法来启动该线程。

public class myThread {
public static void main(String[] args){
Thread t = new newThread();
t.start();
}
} class newThread extends Thread{
@Override
public void run() {
System.out.println(this.getName()+":start!");
}
}

实现Runnable接口

1.新建类实现Runnable接口。

2.重写run方法。该run()方法的方法体就代表了线程需要完成的任务。

3.创建新建类的实例target。

4.以target作为参数创建Thread的实例。

5.调用线程对象的start()方法来启动该线程。

public class myThread {
public static void main(String[] args){
newThread nt = new newThread();
Thread t = new Thread(nt);
t.start();
}
} class newThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":start!");
}
}

两种方法的优点

1.继承Thread这种方法方便易用,更容易获取当前线程对象。

2.实现Runnable接口这种方法可以继承其他父类;多个线程可以共享一个target对象,适合多个相同线程来处理同一份资源的情况。

可否直接调用run()方法开启线程

事实上,线程对象只有调用start()方法才能在新的线程中运行run()方法体中的代码,而直接调用run()方法意味着在当前线程中调用run()方法,即run()方法被当作普通方法处理了,并不会创建新线程。

public class myThread {
public static void main(String[] args){
newThread nt = new newThread();
Thread t = new Thread(nt,"myThread");
t.run();
}
} class newThread implements Runnable{
@Override
public void run() {
System.out.println("Name:"+Thread.currentThread().getName());
}
}
//结果
Name:main

常用API

构造器

Thread() ,Thread(String name)   //可以传入一个字符串或什么也不传入,就是创建一个什么任务也不做的线程

Thread(Runnable target)

Thread(Runnable target,String name)    //传入一个可运行的对象,name作为线程名称

获取线程信息

static Thread currentThread()      //获取当前线程对象

long getID()            //获取线程标识

String getName()     //获取线程名称

int getPriority()     //获取线程优先级

Thread.state getState()     //获取线程状态

public class myThread {
public static void main(String[] args){
newThread nt = new newThread();
Thread t = new Thread(nt,"myThread");
t.start();
newThread.getInformation(Thread.currentThread());
newThread.getInformation(t);
}
} class newThread implements Runnable{
@Override
public void run() {
} static void getInformation(Thread t){
System.out.println("name:"+t.getName());
System.out.println("id:"+t.getId());
System.out.println("priority:"+t.getPriority());
System.out.println("state:"+t.getState());
}
} //结果
name:main
id:1
priority:5
state:RUNNABLE
name:myThread
id:13
priority:5
state:TERMINATED

设置线程信息

void setName()    //设置线程名称

void setPriority()    //设置线程优先级

void setDaemon(Boolean on)   //设置为守护线程,只有当线程调用start()方法之前才可调用

判断线程状态

boolean isAlive()        //判断线程是否死亡,

boolean isDaemon()      //判断线程是否为守护线程

boolean isInterrupted()     //判断线程是否中断,并且将其变为非中断状态

public class myThread {
public static void main(String[] args){
newThread nt = new newThread();
Thread t = new Thread(nt,"myThread");
System.out.println("未调用start()时:"+t.isAlive());
t.setDaemon(true);
t.start();
newThread.getInformation(t);
newThread.getInformation(Thread.currentThread());
}
} class newThread implements Runnable{
@Override
public void run() {
} static void getInformation(Thread t){
System.out.println(t.getName()+"-isAlive:"+t.isAlive());
System.out.println(t.getName()+"-isDaemon:"+t.isDaemon());
System.out.println(t.getName()+"-isInterrupted:"+t.isInterrupted()); }
} //结果
未调用start()时:false
myThread-isAlive:true
myThread-isDaemon:true
myThread-isInterrupted:false
main-isAlive:true
main-isDaemon:false
main-isInterrupted:false

sleep()方法

该方法让当前线程暂停执行一段时间。

static void sleep(long millis)          //暂停millis毫秒

static void sleep(long millis,long nanos)    //暂停millis毫秒+nanos纳秒

join()方法

join意味加入,可以抽象地认为它是加入当前线程队伍,也就是说,发生t.join()调用时调用方t加入当前线程队伍,当前线程需要等待t线程执行完毕后才开始执行。

public class myThread {
public static void main(String[] args)throws InterruptedException {
newThread nt = new newThread();
Thread t = new Thread(nt,"subThread");
t.start();
t.join();
for (int i = 1; i <= 1000; i++) {
if (i%500==0) {
System.out.println("mainThread finish!");
}
} }
} class newThread implements Runnable{
@Override
public void run(){
for (int i = 1; i <= 1000; i++) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (i%500==0)
System.out.println("subThread finish!");
}
}
}

结果如下,主线程显然是比子线程执行时间更短,然而还是主线程最后执行完

subThread finish!
subThread finish!
mainThread finish!
mainThread finish!

方法还有另外两个重载形式

void join(long millis)          //等待millis毫秒

void join(long millis,long nanos)    //等待millis毫秒+nanos纳秒

join()内部使用wait()方法和notifyall()方法来实现的,因而它与sleep()方法的区别是,sleep方法不会释放持有的锁,而join()方法会释放持有的锁。

//将t.join()改为t.join(50,50)后,结果不同:
mainThread finish!
mainThread finish!
subThread finish!
subThread finish!

yield()方法

让出当前线程cup的使用权,此时就绪队列中高优先级 的线程将被执行,此外该方法不释放线程持有的锁。

Java线程类的更多相关文章

  1. Java 线程类的一些常用方法

    线程类的一些常用方法: sleep(): 强迫一个线程睡眠N毫秒.  isAlive(): 判断一个线程是否存活.  join(): 等待线程终止.  activeCount(): 程序中活跃的线程数 ...

  2. 面试问题整理笔记系列 一 Java线程类

    1.sleep()和wait()区别 sleep() 方法:线程主动放弃CPU,使得线程在指定的时间内进入阻塞状态,不能得到CPU 时间,指定的时间一过,线程重新进入可执行状态.典型地,sleep() ...

  3. java线程类图

    Executors创建不同类型的Executor, executor执行不同的runnable task Executor: Runnable:

  4. 如何创建并运行java线程

    本文转载地址:            http://ifeve.com/creating-and-starting-java-threads/ Java线程类也是一个object类,它的实例都继承自j ...

  5. Java线程和进程相关面试题与答案总结

    有几天没有写一写博客了,今天就带给大家一些面试题和参考答案吧! 这些都是上海尚学堂Java培训的学员去面试时遇到的问题,今天总结出来的是Java线程相关类的面试题.把参考答案和解析也发布出来,供大家学 ...

  6. java Thread 类的源码阅读(oracle jdk1.8)

    java线程类的源码分析阅读技巧: 首先阅读thread类重点关注一下几个问题: 1.start() ,启动一个线程是如何实现的? 2.java线程状态机的变化过程以及如何实现的? 3. 1.star ...

  7. Java线程和进程

    一.线程 1.什么是线程: 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.一个进程至少包含一个线程,也可以多个,线程属于进程. 2.Java中线程经历的四个 ...

  8. java: Thread 和 runnable线程类

    java: Thread 和 runnable线程类 Java有2种实现线程的方法:Thread类,Runnable接口.(其实Thread本身就是Runnable的子类) Thread类,默认有ru ...

  9. Java线程池的原理及几类线程池的介绍

    刚刚研究了一下线程池,如果有不足之处,请大家不吝赐教,大家共同学习.共同交流. 在什么情况下使用线程池? 单个任务处理的时间比较短 将需处理的任务的数量大 使用线程池的好处: 减少在创建和销毁线程上所 ...

随机推荐

  1. 原来一条select语句在MySQL是这样执行的《死磕MySQL系列 一》

    前言 看到蒋老师的第一篇文章后就收货颇丰,真是句句戳中痛点. 令我记忆最深的就是为什么知道了一个个技术点,却还是用不好 ?不管是蒋老师所说的Redis还是本系列要展开学习的MySQL. 这是一个值得思 ...

  2. SpringBoot JPA查询映射到自定义实体类

    和 SegmentFault上的文章(https://segmentfault.com/a/1190000021869465)一样, 都是俺账号 场景 举一个简单的栗子: 比如有一个User实体类 @ ...

  3. C++继承体系中的内存分段

    ---------------综述与目录-------------- 讨论这个问题之前我们先明确类的结构,一个类的大概组成,下面的很多分类名词都是我个人杜撰,为的就是让读者看懂能够区分,下面分别分类: ...

  4. 十一:JavaWeb中的监听器(二)

    一.监听域对象中属性的变更的监听器 域对象中属性的变更的事件监听器就是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信 ...

  5. C# 委托讲解

    首先,委托的使用场景:A的某些功能,只有在B需要触发时触发,委托就是用来做中间通讯的渠道. 假设:现在有个大佬A,A有个小弟B,B在受到羞辱时就会通过电话Delegate通知A自己被羞辱了,A在这时就 ...

  6. 【C语言】第1章 程序设计与C语言

    第1章 程序设计与C语言 程序:一组计算机能识别和执行的 指令. 计算机语言:人和计算机交流信息的.计算机和人都能识别的语言 C语言允许用两种注释方式: //:单行注释 可单独占一行 可出现在一行中其 ...

  7. Spring Data JPA实体的生命周期总结

    目录 四种状态 API示例 persist remove merge refresh 参考链接 四种状态 首先以一张图,简单介绍写实体生命周期中四种状态之间的转换关系: 瞬时(New):瞬时对象,刚N ...

  8. 高德地图——控件的添加&删除

    控件属性 visible //bool 默认true ov=new AMap.OverView(); ov.hide(); //ov.show(); 显示/隐藏---表示控件的添加与删除 <!D ...

  9. YOLO V3 原理

    基本思想V1: 将输入图像分成S*S个格子,每隔格子负责预测中心在此格子中的物体. 每个格子预测B个bounding box及其置信度(confidence score),以及C个类别概率. bbox ...

  10. 对抗生成网络GAN

      该方法常用于: 图像生成 图像修复,训练用了MSE+Global+Local数据,其中Global+Local判别式用于全局+局部一致性. 图像超分辨率重构   GAN的基本原理,主要包含两个网络 ...