专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java线程实现原理及相关机制_java线程的实现

temp10 2025-10-02 07:56:27 java教程 1 ℃ 0 评论

Java线程实现原理

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();
    }
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表