网创项目资源网站,wordpress标签大全文档,广东东莞人才招聘网,网站设计运行费用Java线程 前言——阅读10-20分钟#x1f386;1.创建和运行线程ThreadRunableFutureTask多个线程运行方式 #x1f4e3;2.不同操作系统查看进程线程的方法windowslinuxJava命令行 #x1f680;3.java线程运行原理栈与栈帧线程上下文切换#xff08;Thread Context Switch1.创建和运行线程ThreadRunableFutureTask多个线程运行方式 2.不同操作系统查看进程线程的方法windowslinuxJava命令行 3.java线程运行原理栈与栈帧线程上下文切换Thread Context Switch 4.常见的线程API不推荐的方法 5.Runable和Thread的run的区别为什么有 Thread 还要有 Runablestart和run的区别 6.sleep和yield区别SleepYield 7.sleep和wait区别✨8.wait和await区别9.Join方法为什么需要Join 10.interrupt打断 sleep,wait,join已阻塞线程 11.主线程和守护线程什么是守护线程将线程设置为守护线程 12.操作系统线程的5种状态13.Java线程的6种状态本章的重点在于掌握 前言——阅读10-20分钟 本文仅对Java的线程使用学习做个小结不涉及过多底层原理和锁的实现 1.创建和运行线程 Thread
run任务创建和start执行都由线程直接操作
// 创建线程对象
Thread t new Thread() {public void run() {// 要执行的任务};// 启动线程
t.start(); Runable
任务由Runable创建任务由Thread线程执行达到解耦目录执行结果是一样的
Runnable runnable new Runnable() {public void run(){
// 要执行的任务}
};
// 创建线程对象
Thread t new Thread( runnable );
// 启动线程
t.start();FutureTask
FutureTask的作用和Runable一样FutureTask有返回值 Runable 无返回值可以用FutureTask task 接收线程执行的返回值task.get()获取返回值
// 创建任务对象
FutureTaskInteger task3 new FutureTask(() - {log.debug(hello);return 100;
});
// 参数1 是任务对象; 参数2 是线程名字推荐
new Thread(task3, t3).start();
// 主线程阻塞同步等待 task 执行完毕的结果
Integer result task3.get();
log.debug(结果是:{}, result);多个线程运行方式
交替执行谁先谁后不由我们控制由CPU决定 2.不同操作系统查看进程线程的方法 windows
任务管理器可以查看进程和线程数也可以用来杀死进程
tasklist 查看进程taskkill 杀死进程
linux
ps -fe 查看所有进程ps -fT -p 查看某个进程PID的所有线程kill 杀死进程top 按大写 H 切换是否显示线程top -H -p 查看某个进程PID的所有线程
Java命令行
jps 命令查看所有 Java 进程jstack 查看某个 Java 进程PID的所有线程状态jconsole 来查看某个 Java 进程中线程的运行情况图形界面
jconsole 远程监控配置
需要以如下方式运行你的 java 类
java -Djava.rmi.server.hostnameip地址 -Dcom.sun.management.jmxremote -
Dcom.sun.management.jmxremote.port连接端口 -Dcom.sun.management.jmxremote.ssl是否安全连接 -
Dcom.sun.management.jmxremote.authenticate是否认证 java类修改 /etc/hosts 文件将 127.0.0.1 映射至主机名
如果要认证访问还需要做如下步骤
复制 jmxremote.password 文件修改 jmxremote.password 和 jmxremote.access 文件的权限为 600 即文件所有者可读写连接时填入 controlRole用户名RD密码
3.java线程运行原理 栈与栈帧
Java Virtual Machine Stacks Java 虚拟机栈我们都知道 JVM 中由堆、栈、方法区所组成其中栈内存是给谁用的呢其实就是线程每个线程启动后虚拟机就会为其分配一块栈内存。
每个栈由多个栈帧Frame组成对应着每次方法调用时所占用的内存每个线程只能有一个活动栈帧对应着当前正在执行的那个方法
线程上下文切换Thread Context Switch
因为以下一些原因导致 cpu 不再执行当前的线程转而执行另一个线程的代码
线程的 cpu 时间片用完垃圾回收有更高优先级的线程需要运行线程自己调用了 sleep、yield、wait、join、park、synchronized、lock 等方法
当 Context Switch 发生时需要由操作系统保存当前线程的状态并恢复另一个线程的状态Java 中对应的概念就是程序计数器Program Counter Register它的作用是记住下一条 jvm 指令的执行地址是线程私有的
状态包括程序计数器、虚拟机栈中每个栈帧的信息如局部变量、操作数栈、返回地址等Context Switch 频繁发生会影响性能
开启IDEA的debugger模式这里每一行对应一个栈帧
read方法main方法先进后出先运行的在栈底
一个线程对应一个方法栈
线程t1和t2 4.常见的线程API 不推荐的方法 5.Runable和Thread的run的区别
通过组合的方式调用run从源码角度实际都是同一个run方法
源码中Runable重载run再传参给Thread,在Thread的中判断 Runable 不空优先调用 Runable 的方法否则就是Thread的run方法但其实Runable的run方法的内部还是Thread的run方法
直接在Thread重载run方法则运行时运行重载的方法
为什么有 Thread 还要有 Runable
因为有的场景下我们需要把任务和执行两者分开解耦
Thread创建run任务并start执行任务和执行都耦合在Thread对象中Runable用来创建任务以传参的方式将 Runable所带的任务传入Thread然后让Thread执行就实现了任务和执行的解耦
有人会问什么情况下需要这种分离的玩意?
消息队列: 生产者消费者就是执行者队列里面的就是任务凡是需要创建任务和执行任务分离的场景都可以尝试使用进行解耦 start和run的区别
直接调用 run 是在主线程中执行了 run没有启动新的线程使用 start 是启动新的线程通过新的线程间接执行 run 中的代码start并不会马上执行只是让线程进入就绪态只有他抢到CPU才能执行 6.sleep和yield区别 Sleep
调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态阻塞其它线程可以使用 interrupt 方法打断正在睡眠的线程这时 sleep 方法会抛出 InterruptedException睡眠结束后的线程未必会立刻得到执行而是进入 Runnable 就绪状态建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性不会释放锁只跟线程相关
Yield
调用 yield 会让当前线程从 Running 进入 Runnable 就绪状态然后调度执行其它线程2. 具体的实现依赖于操作系统的任务调度器
7.sleep和wait区别
涉及到锁此篇只涉及线程在后篇补充
✨8.wait和await区别
涉及到锁此篇只涉及线程在后篇补充 9.Join方法 为什么需要Join
因为多线程是并发执行的每个执行完成的顺序是不能确定的。意思如果有线程调用 t2.join()并运行到t2.join()这个位置会阻塞直到t2线程执行结束当前线程才能继续往下执行
private static void test2() throws InterruptedException {Thread t1 new Thread(() - {sleep(1);r1 10;});Thread t2 new Thread(() - {sleep(2);r2 20;});long start System.currentTimeMillis();t1.start();t2.start();t1.join();---- // 运行到此卡住直到t1执行完t2.join();-----// 运行到此卡住, 直到t2执行完long end System.currentTimeMillis();log.debug(r1: {} r2: {} cost: {}, r1, r2, end - start);
}10.interrupt
interrupt打断线程分两种情况:
打断正常运行的线程打断sleepwaitjoin 已阻塞线程 打断 sleep,wait,join已阻塞线程
首先声明不使用stop()打断线程的原因
stop()打断线程会直接杀死线程不会给线程释放锁dd料理后事的机会资源得不到释放
如下例子就是可以处理后事线程
sleep,wait,join在这里可以看成是一样的阻塞态(当然三者的阻塞肯定在细节上有不同但是这里只要是阻塞就行了)
class TPTInterrupt {private Thread thread;public void start(){thread new Thread(() - {while(true) {Thread current Thread.currentThread();if(current.isInterrupted()) {log.debug(料理后事);break;}try {Thread.sleep(1000);log.debug(将结果保存);} catch (InterruptedException e) {current.interrupt();}
// 执行监控操作}},监控线程);thread.start();}public void stop() {thread.interrupt();}}--------------------------------------------------TPTInterrupt t new TPTInterrupt();
t.start();
Thread.sleep(3500);
log.debug(stop);
t.stop();主要依赖这三个函数的特点处理后事
因为sleep,wait,join也会设置打断标记而处理后事的判断条件就是打断标记通过这个标记来手动做return结束线程而不是直接stop杀死进程 11.主线程和守护线程 什么是守护线程
默认情况下Java 进程需要等待所有线程都运行结束才会结束。有一种特殊的线程叫做守护线程只要其它非守护线程运行结束了即使守护线程的代码没有执行完也会强制结束。
比如
垃圾回收器线程就是一种守护线程Tomcat 中的 Acceptor 和 Poller 线程都是守护线程所以 Tomcat 接收到 shutdown 命令后不会等待它们处理完当前请求直接结束 将线程设置为守护线程
Thread t1 new Thread(() - {
log.debug(开始运行...);
sleep(2);
log.debug(运行结束...);
}, daemon);
// 设置该线程为守护线程
t1.setDaemon(true);----------//设置为守护线程
t1.start(); 12.操作系统线程的5种状态 13.Java线程的6种状态 NEW 线程刚被创建但是还没有调用 start() 方法RUNNABLE 当调用了 start() 方法之后注意Java API 层面的 RUNNABLE 状态涵盖了 操作系统 层面的【可运行状态】、【运行状态】和【阻塞状态】由于 BIO 导致的线程阻塞在 Java 里无法区分仍然认为是可运行BLOCKED WAITING TIMED_WAITING 都是 Java API 层面对【阻塞状态】的细分后面会在状态转换详述TERMINATED 当线程代码运行结束
本章的重点在于掌握
线程创建线程重要 api如 startrunsleepjoininterrupt 等线程状态应用方面 异步调用主线程执行期间其它线程异步执行耗时操作提高效率并行计算缩短运算时间同步等待join统筹规划合理使用线程得到最优效果 原理方面 线程运行流程栈、栈帧、上下文切换、程序计数器Thread 两种创建方式 的源码 模式方面 终止模式之两阶段终止
6种状态