手机网站qq代码,百度搜索关键词排名,法治中国建设网站,花都网站制作公司【JAVAEE】多线程 一、进程1.1 进程的定义1.2 进程和线程的联系 二、线程2.1 JConsole工具2.2 创建线程2.2.1 Thread类#xff0c;start#xff08;#xff09;#xff0c;run#xff08;#xff09;2.2.2 继承Thread类2.2.3 实现Runnable接口2.2.4 匿名内部类2.2.5 使用… 【JAVAEE】多线程 一、进程1.1 进程的定义1.2 进程和线程的联系 二、线程2.1 JConsole工具2.2 创建线程2.2.1 Thread类startrun2.2.2 继承Thread类2.2.3 实现Runnable接口2.2.4 匿名内部类2.2.5 使用Runnable接口的匿名内部类2.2.6 使用lambda表达式 2.3 Thread类及常用方法2.3.1 Thread类的构造方法2.3.2 Thread类的常见属性 2.4 线程状态2.5 后台线程和前台线程2.6 休眠线程2.7 线程等待2.8 终止线程2.8.1 自定义标志位终止线程2.8.2 使用自带标志位终止线程 博客结尾包含此篇博客的全部代码 一、进程
1.1 进程的定义 进程Process是计算机操作系统中的一个核心概念它是程序在计算机上的一次动态执行实例。换句话说进程是程序运行时的活动表现形式。它包含了程序代码、数据、运行状态以及系统资源的分配情况。进程相当于一个正在运行的程序。进程也是系统分配资源的基本单位。 1.2 进程和线程的联系
首先并发编程成为我们的需求每个客户端给服务器发送请求服务器就需要给客户端提供服务。在90年代多进程是一种解决方案
那么既然有解决方法为什么还要引入线程 线程线程是轻量级的进程
线程相比于进程
创建线程比创建进程更快。销毁线程比销毁进程更快。调度线程比调度进程更快。
举个例子
假设这个任务是“消灭”桌子上的两只鸡在一个房间中有一个桌子桌子上放了两只鸡。 进程的解决方法再创建一个房间将这两只鸡分开分别“消灭”。 线程的解决方法在这个房间中“消灭”这两只鸡。 这两个对比你发现相同的人数进程需要再创建一个房间开销很大而线程则啥都不需要添加。
二、线程
2.1 JConsole工具
在创建线程之前先给大家介绍一下JConsole 工具 JConsole是JDK 自带的一款图形化监控和管理工具基于 JMXJava Management Extensions技术实现。它能够连接到本地或远程的 Java 虚拟机JVM并实时监控和管理 Java 应用程序的性能和资源使用情况。 这里我们就用它来监控我们的线程 JConsole找到我们的JDK安装的安装路径像我这里安装的JDK17–bin–jconsole.exe 如何使用 测试代码代码运行起来才能观察到如果线程结束就观察不到。
class MyThread extends Thread {Overridepublic void run() {while (true) {System.out.println( hello Thread);}}
}public class Demo1 {public static void main(String[] args) {MyThread t1 new MyThread();t1.start();}
}刚进去出现不安全连接由于是我是自己练习所以点不安全连接。
2.2 创建线程
2.2.1 Thread类startrun Thread类线程是操作系统的概念操作系统定义了一些api应用程序编程接口来供程序员使用而java中将这些api封装成Thread类来供使用Thread类在java.long这个包中所以用的时候不需要导包。start用于启动一个新线程线程调度器会调用 run() 方法。start() 方法只能被调用一次。如果尝试多次调用 start()会抛出 IllegalThreadStateException 异常。run定义线程的执行逻辑但不会启动新线程。如果需要启动新线程必须通过 start() 方法。相当于线程的入口。 2.2.2 继承Thread类
代码
class MyThread extends Thread {Overridepublic void run() {while (true) {System.out.println( hello Thread);}}
}public class Demo1 {public static void main(String[] args) {MyThread t1 new MyThread();t1.start();while(true) {System.out.println( hello main);}}
}2.2.3 实现Runnable接口
实现Runnable接口的MyRunnnable类将new MyRunnable()当作一个对象传给Thread的构造函数。 代码
class MyRunnable implements Runnable {Overridepublic void run() {System.out.println(Hello Thread);}
}public class Demo2 {public static void main(String[] args) {Thread t1 new Thread(new MyRunnable());t1.start();}
}2.2.4 匿名内部类
public class Demo3 {public static void main(String[] args) {Thread thread new Thread(){Overridepublic void run() {System.out.println(Hello Thread);}};thread.start();System.out.println(Hello main);}
}2.2.5 使用Runnable接口的匿名内部类
public class Demo4 {public static void main(String[] args) {Thread t1 new Thread(new Runnable(){Overridepublic void run() {System.out.println(Hello Thread);}});t1.start();}
}2.2.6 使用lambda表达式
public class Demo5 {public static void main(String[] args) {Thread thread new Thread(()-{while(true){System.out.println(Hello Thread);}});thread.start();while(true){System.out.println(Hello main);}}
}2.3 Thread类及常用方法
2.3.1 Thread类的构造方法 解释一下第四个ThreadRunnable targetString name! public class Demo6 {public static void main(String[] args) {Thread thread new Thread(new Runnable() {Overridepublic void run() {while (true) {System.out.println(Hello Thread);}}}, Thread1);thread.start();while (true) {System.out.println(Hello main);}}
} 2.3.2 Thread类的常见属性 • ID 是线程的唯⼀标识不同线程不会重复 • 获取线程的名称 • 获取线程的当前状态如新建、就绪、运行、阻塞、等待、终止等 • 优先级⾼的线程理论上来说更容易被调度到 • 关于后台线程需要记住⼀点JVM会在⼀个进程的所有⾮后台线程结束后才会结束运⾏。 • 是否存活即简单的理解为 run ⽅法是否运⾏结束了 • 判断线程是否被中断。线程的中断状态可以通过调用 interrupt() 方法来设置该方法会改变线程的中断状态但不会停止线程的执行
2.4 线程状态
public class Demo7 {public static void main(String[] args) {for(Thread.State state: Thread.State.values()) {System.out.println(state);}}
}获取线程的所有状态 • NEW: 当线程对象被创建但尚未调用 start() 方法时线程处于新建状态。在这个状态下线程尚未开始执行。 public class Demo7 {public static void main(String[] args) {Thread threadnew Thread(()-{System.out.println(Hello Thread);});System.out.println(thread.getState());thread.start();}
}• RUNNABLE: 当调用线程的 start() 方法后线程进入就绪状态。在这个状态下线程已经准备好运行等待 CPU 时间片以便执行。就绪状态的线程可能正在 JVM 中运行也可能正在等待操作系统调度。 public class Demo7 {public static void main(String[] args) throws InterruptedException {Thread threadnew Thread(()-{for(int i0;i3;i) {System.out.println(Hello Thread);}});System.out.println(thread.getState());thread.start();System.out.println(thread.getState());}
}• BLOCKED: 由锁导致的后面会出一篇关于线程安全问题到时候会详细介绍这里就不过多介绍了 当线程等待获取一个排他锁如同步块或同步方法中的锁时线程进入阻塞状态。线程在等待锁释放后才能继续执行。阻塞状态的线程不会被分配 CPU 时间片。 • WAITING: 时间阻塞这个等待是没时间上限的 当线程执行 wait()、join() 或 LockSupport.park() 方法后线程进入等待状态。在这个状态下线程需要等待其他线程执行特定的操作如通知或中断才能继续。等待状态的线程不会被分配 CPU 时间片。 public class Demo7 {public static void main(String[] args) throws InterruptedException {Thread threadnew Thread(()-{while(true) {}});System.out.println(thread.getState());thread.start();thread.join();}
}发现main线程是waiting。
• TIMED_WAITING: 时间阻塞这个等待是有时间上限的不参与CPU调度
public class Demo7 {public static void main(String[] args) throws InterruptedException {Thread threadnew Thread(()-{while(true) {try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});System.out.println(thread.getState());thread.start();Thread.sleep(1000);System.out.println(thread.getState());}
}• TERMINATED: 当线程的 run() 方法执行完毕或者线程被 stop() 方法已废弃强制停止或者线程抛出未捕获的异常导致运行结束时线程进入终止状态。在这个状态下线程已经结束执行不再消耗任何资源。 public class Demo7 {public static void main(String[] args) throws InterruptedException {Thread threadnew Thread(()-{for(int i0;i3;i) {System.out.println(Hello Thread);}});System.out.println(thread.getState());thread.start();Thread.sleep(6000);System.out.println(thread.getState());}
}2.5 后台线程和前台线程
前台线程一般我们创建的线程都是前台线程只要前台线程不结束JVM就不会退出。 后台线程也称守护线程后台线程一般都是辅助性的任务如果前台线程全部结束即使还有后台线程在运行JAM也会退出。
public class Demo8 {public static void main(String[] args) {Thread thread1new Thread(()-{for(int i0;i2;i){System.out.println(Hello Thread);}});thread1.start();System.out.println(thread1.isDaemon());//false 说明他不是守护线程Thread thread2new Thread(()-{for(int i0;i2;i){System.out.println(Hello Thread);}});thread2.setDaemon(true);thread2.start();System.out.println(thread2.isDaemon());//true}
}2.6 休眠线程 下面那个可以达到纳秒级别这种适用于军工航天等之类一把情况下用不到。 这里还有一个需要注意的是由于 Runnable 接口的 run 方法没有 throws 子句所以这里只能用try-catch 来捕获异常。
2.7 线程等待 public class Demo10 {public static void main(String[] args) throws InterruptedException {Thread thread new Thread(()-{for (int i 0; i 3; i){System.out.println(Hello Thread);}});thread.start();thread.join();System.out.println(Hello main);}
}先执行thread线程thread线程执行完再执行main线程。为了防止死等也可以设置等待时间。
2.8 终止线程
让run方法尽快结束。
2.8.1 自定义标志位终止线程
public class Demo11 {public static boolean flagtrue;public static void main(String[] args) throws InterruptedException {Thread thread new Thread(()-{while(flag){System.out.println(Hello Thread);}System.out.println(Bye Bye Thread);});thread.start();Thread.sleep(1000);flagfalse;}
}将flag设置为全局变量这里就是匿名内部类访问外部类而不是变量捕获。 为什么不可以将flag设置为局部变量 很有可能是main线程已经执行完已经将flag销毁了但是Thread线程中还没执行到while(flag)… 2.8.2 使用自带标志位终止线程 Java自带标志位来结束终止线程。先使用Thread.currentThread()来获取当前线程在.isInterrupted()获取标志位。然后再主进程中调用interrupte()方法来将标志位值修改为true。
public class Demo12 {public static void main(String[] args) throws InterruptedException {Thread thread new Thread(() - {while (!Thread.currentThread().interrupted()) {System.out.println(Hello Thread);}System.out.println(Bye Bye Thread);});thread.start();Thread.sleep(1000);thread.interrupt();}
}
调用interrupte()方法不仅会设置标志位还会提前唤起sleep阻塞
public class Demo12 {public static void main(String[] args) throws InterruptedException {Thread thread new Thread(() -{while (!Thread.currentThread().isInterrupted()) {System.out.println(hahah);try {Thread.sleep(1000);} catch (InterruptedException e) {//1.不操作继续执行线程因为sleep唤醒后会又将标志位改为truee.printStackTrace();//2.结束线程break;//3.进行其它操作}}});thread.start();Thread.sleep(1000);thread.interrupt();}
}此篇博客的全部代码