做网站 蓝洋,网站诊断seo当前数据是指,中山精品网站建设新闻,创业新项目戳蓝字“CSDN云计算”关注我们哦#xff01;什么是线程试想一下没有线程的程序是怎么样的#xff1f;百度网盘在上传文件时就无法下载文件了#xff0c;得等文件上传完成后才能下载文件。这个我们现在看起来很反人性#xff0c;因为我们习惯了一个程序同时可以进行运行多个… 戳蓝字“CSDN云计算”关注我们哦什么是线程试想一下没有线程的程序是怎么样的百度网盘在上传文件时就无法下载文件了得等文件上传完成后才能下载文件。这个我们现在看起来很反人性因为我们习惯了一个程序同时可以进行运行多个功能而这些都是线程的功劳。之前的文章 进程知多少 中讲到为了实现多个程序并行执行引入了进程概念。现在引入线程是为了让一个程序能够并发执行。线程的组成线程ID线程标识符。当前指令指针PC指向要执行的指令。寄存器集合存储单元寄存器的集合。堆栈暂时存放数据和地址一般用来保护断点和现场。线程与进程区别线程和进程之间的区别我觉得可以用这个例子来看出两者的不同进程就是一栋房子房子住着 3 个人线程就是住在房子里的人。进程是一个独立的个体有自己的资源线程是在进程里的多个线程共享着进程的资源。线程状态我们看到 Java 源代码里面线程状态的枚举有如下 6 个。public enum State {//新建状态NEW,//运行状态RUNNABLE,//阻塞状态BLOCKED,//等待状态WAITING,//等待状态区别在于这个有等待的时间TIMED_WAITING,//终止状态TERMINATED;
}下面给这 6 个状态一一做下解释。NEW新建状态。在创建完 Thread 还没执行 start() 之前线程的状态一直是 NEW。可以说这个时候还没有真正的一个线程映射着只是一个对象。RUNNABLE运行状态。线程对象调用 start() 之后就进入 RUNNABLE 状态该状态说明在 JVM 中有一个真实的线程存在。BLOCKED阻塞状态。线程在等待锁的释放也就是等待获取 monitor 锁。WAITING等待状态。线程在这个状态的时候不会被分配 CPU而且需要被显示地唤醒否则会一直等待下去。TIMED_WAITING超时等待状态。这个状态的线程也一样不会被分配 CPU但是它不会无限等待下去有时间限制时间一到就停止等待。TERMINATED终止状态。线程执行完成结束但不代表这个对象已经没有了对象可能还是存在的只是线程不存在了。线程既然有这么多个状态那肯定就有状态机也就是在什么情况下 A 状态会变成 B 状态。下面就来简单描述一下。结合下图我们 new 出线程类的时候就是 NEW 状态调用 start() 方法就进入了 RUNNABLE 状态这时如果触发等待则进入了 WAITING 状态如果触发超时等待则进入 TIMED_WAITING 状态当访问需要同步的资源时则只有一个线程能访问其他线程就进入 BLOCKED 状态当线程执行完后进入 TERMINATED 状态。图片来源于网路侵删其实在 JVM 中线程是有 9 个状态如下所示有兴趣的同学可以深入了解一下。javaClasses.hpp
enum ThreadStatus {NEW 0,RUNNABLE JVMTI_THREAD_STATE_ALIVE // runnable / runningJVMTI_THREAD_STATE_RUNNABLE,SLEEPING JVMTI_THREAD_STATE_ALIVE // Thread.sleep()JVMTI_THREAD_STATE_WAITING JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT JVMTI_THREAD_STATE_SLEEPING,IN_OBJECT_WAIT JVMTI_THREAD_STATE_ALIVE // Object.wait()JVMTI_THREAD_STATE_WAITING JVMTI_THREAD_STATE_WAITING_INDEFINITELY JVMTI_THREAD_STATE_IN_OBJECT_WAIT,IN_OBJECT_WAIT_TIMED JVMTI_THREAD_STATE_ALIVE // Object.wait(long)JVMTI_THREAD_STATE_WAITING JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT JVMTI_THREAD_STATE_IN_OBJECT_WAIT,PARKED JVMTI_THREAD_STATE_ALIVE // LockSupport.park()JVMTI_THREAD_STATE_WAITING JVMTI_THREAD_STATE_WAITING_INDEFINITELY JVMTI_THREAD_STATE_PARKED,PARKED_TIMED JVMTI_THREAD_STATE_ALIVE // LockSupport.park(long)JVMTI_THREAD_STATE_WAITING JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT JVMTI_THREAD_STATE_PARKED,BLOCKED_ON_MONITOR_ENTER JVMTI_THREAD_STATE_ALIVE // (re-)entering a synchronization blockJVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER,TERMINATED JVMTI_THREAD_STATE_TERMINATED
};Java 线程实现下面讲一讲在 Java 中如何创建一个线程。众所周知实现 Java 线程有 2 种方式继承 Thread 类和实现 Runnable 接口。继承 Thread 类继承 Thread 类重写 run() 方法。class MyThread extends Thread {Overridepublic void run() {System.out.println(MyThread);}}实现 Runnable 接口实现 Runnable 接口实现 run() 方法。class MyRunnable implements Runnable {public void run() {System.out.println(MyRunnable);}}这 2 种线程的启动方式也不一样。MyThread 是一个线程类所以可以直接 new 出一个对象出来接着调用 start() 方法来启动线程而 MyRunnable 只是一个普通的类需要 new 出线程基类 Thread 对象将 MyRunnable 对象传进去。下面是启动线程的方式public class ThreadImpl {public static void main(String[] args) {MyThread myThread new MyThread();Thread myRunnable new Thread(new MyRunnable());System.out.println(main Thread begin);myThread.start();myRunnable.start();System.out.println(main Thread end);}}打印结果如下main Thread begin
main Thread end
MyThread
MyRunnable看这结果不像咱们之前的串行执行依次打印主线程不会等待子线程执行完。敲重点不能直接调用 run()直接调用 run() 不会创建线程而是主线程直接执行 run() 的内容相当于执行普通函数。这时就是串行执行的。看下面代码public class ThreadImpl {public static void main(String[] args) {MyThread myThread new MyThread();Thread myRunnable new Thread(new MyRunnable());System.out.println(main Thread begin);myThread.run();myRunnable.run();System.out.println(main Thread end);}}打印结果main Thread begin
MyThread
MyRunnable
main Thread end
从结果看出只是串行的但看不出没有线程我们看下面例子来验证直接调用
run() 方法没有创建新的线程使用 VisualVM 工具来观察线程情况。我们对代码做一下
修改加上 Thread.sleep(1000000) 让它睡眠一段时间这样方便用工具查看线程情况。
调用 run() 的代码public class ThreadImpl {public static void main(String[] args) {MyThread myThread new MyThread();myThread.setName(MyThread);Thread myRunnable new Thread(new MyRunnable());myRunnable.setName(MyRunnable);System.out.println(main Thread begin);myThread.run();myRunnable.run();System.out.println(main Thread end);try {Thread.sleep(1000000);} catch (InterruptedException e) {e.printStackTrace();}}}class MyThread extends Thread {Overridepublic void run() {System.out.println(MyThread);try {Thread.sleep(1000000);} catch (InterruptedException e) {e.printStackTrace();}}}class MyRunnable implements Runnable {public void run() {System.out.println(MyRunnable);try {Thread.sleep(1000000);} catch (InterruptedException e) {e.printStackTrace();}}}运行结果main Thread begin
MyThread只打印出 2 句日志观察线程时也只看到 main 线程没有看到 MyThread 和 MyRunnable 线程印证了上面咱们说的直接调用 run() 方法没有创建线程。下面我们来看看有调用 start() 的代码public class ThreadImpl {public static void main(String[] args) {MyThread myThread new MyThread();myThread.setName(MyThread);Thread myRunnable new Thread(new MyRunnable());myRunnable.setName(MyRunnable);System.out.println(main Thread begin);myThread.start();myRunnable.start();System.out.println(main Thread end);try {Thread.sleep(1000000);} catch (InterruptedException e) {e.printStackTrace();}}}运行结果main Thread begin
main Thread end
MyThread
MyRunnable所有日志都打印出来了并且通过 VisualVM 工具可以看到 MyThread 和 MyRunnable 线程。看到了这个结果切记创建线程要调用 start() 方法。福利扫描添加小编微信备注“姓名公司职位”加入【云计算学习交流群】和志同道合的朋友们共同打卡学习推荐阅读干货分享: 服务器处理器基础知识盘点2019十大科技并购IBM收购红帽居首阿里考拉仅排第十英特尔20亿美元收购Habana Labs柳传志将卸任联想……程序员创业前要做哪些准备倒计时 3 天 | 年前不学习年后无加薪区块链开发者们不要纠结了内含赠票福利高通2 亿像素手机 2020 年诞生超模脸、网红脸、萌娃脸...换头像不重样我开源了5款人脸生成器真香朕在看了