网站首页 > java教程 正文
Java线程实现原理
Java线程启动执行底层实现流程图,Java线程属于内核级线程,所以说频繁的创建线程耗时耗资源的过程。内核级线程是依赖于内核的,即无论是用户进程中的线程还是系统进程中的线程,它们的创建、撤消、切换都是由内核实现的。用户级线程,操作系统不知道应用线程的存在。
Java线程的调度机制
线程的调度是指操作系统为线程分配处理器使用权的过程,主要的调度方式分为两种,协同式线程调度和抢占式线程调度。
协同式线程调度
线程的执行时间由线程本身来控制,线程把自己的工作执行完成后,要主动的通知系统切换到另一个线程上。该调度方式最大的好处是简单,且切换操作对线程自己是可知的,没有线程同步问题,坏处是线程的执行时间不可控制,如果一个线程有问题可能一直阻塞在那里。
抢占式线程调度
每个线程由系统来分配执行时间,线程的切换不由线程本身来决定,Java中yield()可以让出执行时间,但无法获取执行时间,线程的执行时间系统可控制,也不会出现有一个线程阻塞导致整个进程阻塞。
Java线程间通信
volatile
volatile有两大特性,一是可见性,二是有序性,禁止指令重排序,其中可见性可以让线程之间进行通信。
/**
* 线程通信,volatile可见性实现案例
* @Author warrior
**/
public class ThreadCommunicationVolatileDemo {
/**
* 亮灯状态
*/
private static volatile boolean lightUp = false;
public static void main(String[] args) {
/**
* 创建一个开灯线程,当灯关闭时开灯
*/
Thread turnOnLightThread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if(!lightUp){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//开灯
lightUp = true;
System.out.println(Thread.currentThread().getName() + " 开灯");
}
}
}
},"turn_on_thread");
//开启线程
turnOnLightThread.start();
/**
* 创建一个关灯线程,当灯亮时关灯
*/
Thread turnOffLightThread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if(lightUp){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//关灯
lightUp = false;
System.out.println(Thread.currentThread().getName() + " 关灯");
}
}
}
},"turn_off_thread");
//开启线程
turnOffLightThread.start();
}
}
等待唤醒(等待通知)机制
wait和notify
等待唤醒机制可以基于wait和notify方法来实现,在一个线程内调用该线程锁对象的wait方法,线程将进入等待队列进行等待直到被唤醒。
/**
* 线程通信,wait和notify实现案例
*
* @Author warrior
**/
public class ThreadWaitNotifyDemo {
//定义锁对象
private static final Object lock = new Object();
//定义灯的状态
private static boolean lightUp = false;
public static void main(String[] args) {
/**
* 创建一个开灯线程,当灯关闭时开灯
*/
Thread turnOnLightThread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
synchronized (lock) {
if (lightUp) {
//灯亮,等待关灯
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//开灯
lightUp = true;
System.out.println(Thread.currentThread().getName() + " 开灯");
//通知关灯线程
lock.notify();
}
}
}
}, "turn_on_thread");
//开启线程
turnOnLightThread.start();
/**
* 创建一个关灯线程,当灯亮时关灯
*/
Thread turnOffThread = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
synchronized (lock) {
if(!lightUp){
//灯灭,等待开灯
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//关灯
lightUp = false;
System.out.println(Thread.currentThread().getName() + " 关灯");
//通知开灯线程
lock.notify();
}
}
}
},"turn_off_thread");
//开启线程
turnOffThread.start();
}
}
LockSupport
LockSupport是JDK中用来实现线程阻塞和唤醒的工具,线程调用park则等待许可,调用unpark则为线程指定许可。使用它可以在任何场景使线程阻塞,可以指定任何线程进行唤醒,并且不用担心阻塞和唤醒的顺序,但是要注意连续多次唤醒和一次唤醒是一样的。
import java.util.concurrent.locks.LockSupport;
/**
* 线程通信,LockSupport实现案例
*
* @Author warrior
**/
public class ThreadLockSupportDemo {
//定义开灯状态
private static boolean lightUp = false;
public static void main(String[] args) {
/**
* 创建一个开灯线程,当灯关闭时开灯
*/
Thread turnOnLightThread = new Thread(new Runnable() {
@Override
public void run() {
if (lightUp) {
//灯亮,等待关灯
LockSupport.park();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//开灯
lightUp = true;
System.out.println(Thread.currentThread().getName() + " 开灯");
}
}, "turn_on_thread");
//开启线程
turnOnLightThread.start();
//通知关灯线程
LockSupport.unpark(turnOnLightThread);
}
}
管道输入/输出流
管道输入/输出流和普通文件输入/输出流、网络输入/输出流不同之处在于它主要用于线程间的数据传输,而传输的媒介为内容。管道输入/输出流主要包括四种具体实现:PipedOutputStream、PipedInputStream、PipedReader和PipedWriter,前两者面向字节流,后两者面向字符流。
/**
* 线程通信,PipedReader和PipedWriter实现案例
* @Author warrior
**/
public class ThreadPipedDemo {
public static void main(String[] args) throws IOException {
PipedReader in = new PipedReader();
PipedWriter out = new PipedWriter();
//将输出流和输入流进行连接,否则在使用时会抛出IOException
out.connect(in);
/**
* 创建一个线程,用于读取输入流中的数据
*/
Thread printThread = new Print(in);
//开启线程
printThread.start();
int receive = 0;
try {
while ((receive = System.in.read()) != -1) {
out.write(receive);
}
} finally {
out.close();
}
}
static class Print extends Thread {
private PipedReader in;
public Print(PipedReader in) {
this.in = in;
}
@Override
public void run() {
int receive = 0;
try {
while ((receive = in.read()) != -1) {
System.out.print((char) receive);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
Thrad.join
join可以理解成线程的合并,当一个线程调用另一个线程的join方法时,当前线程阻塞等待被调用join方法的线程执行完成才能继续执行,所以join的好处是能保证线程的执行顺序,当时如果调用线程的join方法其实已经失去了并行的意义,虽然存在多个线程本质上还是串行的,join的实现其实是基于等待通知机制。
/**
* 线程join案例
* @Author warrior
**/
public class ThreadJoinDemo {
public static void main(String[] args) throws InterruptedException {
/**
* 创建一个线程,模拟执行任务需要5s
*/
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + "开始执行任务");
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName() + "任务执行完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
long start = System.currentTimeMillis();
//开启线程
thread.start();
//主线程等待该子线程执行完成
thread.join();
System.out.println("执行时间:" + (System.currentTimeMillis() - start));
System.out.println(Thread.currentThread().getName() + "主线程执行完成");
}
}
Java线程的中断机制
Java没有提供一种安全、直接的方法来停止某个线程,而是提供了一种中断机制。中断机制其实是一种协作机制,通过中断并不能直接终止另一个线程,而是需要被中断的线程自己处理。被中断的线程完全拥有自主权,它可以选择立即停止,也可以选中一段时间后停止,也可以选择压根不停止。
API的使用
- interrupt():将线程的中断标志位设置为true,不会停止线程。
- isInterrupted():判断当前线程的中断标志位是否为true,不会清除中断标志位。
- Thread.interrupted():判断当前线程的中断标志位是否位true,并清除中断标志位,重置位false。
/**
* 线程中断API使用案例
*
* @Author warrior
**/
public class ThreadInterruptDemo {
private static int i = 0;
public static void main(String[] args) throws InterruptedException {
/**
* 创建一个线程执行i++操作
*/
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
i++;
System.out.println(i);
//判断当前线程的中断标志位是否true,并清除中断标志位,重置为false
//Thread.interrupted();
//isInterrupted 判断中断标志位,不会清除中断标志位
if(Thread.currentThread().isInterrupted()){
System.out.println(Thread.currentThread().getName() + ",中断标志位为ture...");
break;
}
}
}
});
//开启线程
thread.start();
Thread.sleep(1000);
//interrupt()设置线程的中断标志位为false,不会终止线程
thread.interrupt();
}
}
sleep期间的中断
处于休眠中的线程被中断,线程是可以感受到中断信号的,并且会抛出一个InterruptException异常,同时清除中断信号,并将中断标志位设置为false,有可能导致线程无法正确的停止。
/**
* sleep 线程中断案例
*
* @Author warrior
**/
public class ThreadInterruptStopDemo {
private static int count = 0;
public static void main(String[] args) throws InterruptedException {
/**
* 创建一个线程,执行10000次count++操作
*/
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted() && count < 10000) {
System.out.println(Thread.currentThread().getName() + " count:" + count++);
/**
* sleep期间,线程可以感受到中断信号,会抛出一个InterruptedException异常,同时中断标志位会被清除,并将中断标志位设置位false
*/
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
//重新设置线程中断状态位ture
Thread.currentThread().interrupt();
}
}
System.out.println(Thread.currentThread().getName() + " 线程执行完成");
}
});
//开启线程
thread.start();
//主线程等待1s
Thread.sleep(1000);
//中断线程
thread.interrupt();
}
}
利用中断机制优雅停止线程
/**
* 利用中断机制优雅停止线程案例
* @Author warrior
**/
public class ThreadStopDemo {
private static int count = 0;
public static void main(String[] args) throws InterruptedException {
/**
* 创建一个线程,执行10000次count++操作
*/
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while(!Thread.currentThread().isInterrupted() && count < 10000){
System.out.println(Thread.currentThread().getName() + " count:" + count++);
}
}
});
//开启线程
thread.start();
Thread.sleep(5);
//中断线程
thread.interrupt();
}
}
猜你喜欢
- 2025-10-02 java线程终止 interrupt 关键字详解
- 2025-10-02 Java处理百万级消息积压方案_java 实时处理亿级数据
- 2025-10-02 阻塞模型将会使线程休眠,为什么 Java 线程状态却是 RUNNABLE?
- 2025-10-02 安卓7系统设置永不休眠_android 设置永不休眠
你 发表评论:
欢迎- 最近发表
-
- JUC系列之《CompletableFuture:Java异步编程的终极武器》
- SpringBoot+Jasync异步化改造狂降90%耗时,百万并发下的性能杀戮
- Java异步编程神器:CompletableFuture实战技巧
- Spring Boot 异步请求 + 虚拟线程性能提升?结果很意外
- 异步可以单线程,但高并发的异步肯定要用线程池
- Java线程实现原理及相关机制_java线程的实现
- java线程终止 interrupt 关键字详解
- Java处理百万级消息积压方案_java 实时处理亿级数据
- 阻塞模型将会使线程休眠,为什么 Java 线程状态却是 RUNNABLE?
- 安卓7系统设置永不休眠_android 设置永不休眠
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)