• 线程停止与中断、线程间通信三种方式


    线程停止、中断

    如何停止一个运行中的线程???

    通过volatile变量实现线程停止
    /**
     * 停止一个运行线程 & volatile
     */
    public class StopThreadTest01 {
    
        static volatile boolean flag=false;
    
        public static void main(String[] args) {
            new Thread(()->{
                while (true){
                    if (flag){
                        System.out.println("stop...");
                        break;
                    }
                    try {
                        TimeUnit.MILLISECONDS.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("run...");
                }
            },"t1").start();
    
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(()->{
                flag=true;
            },"t2").start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    通过AtomicBoolean停止线程
    /**
     * 停止一个运行线程 & AtomicBoolean(原子类)
     */
    public class StopThreadTest02 {
    
        static AtomicBoolean flag= new AtomicBoolean(false);
    
        public static void main(String[] args) {
            new Thread(()->{
                while (true){
                    if (flag.get()){
                        System.out.println("stop...");
                        break;
                    }
                    try {
                        TimeUnit.MILLISECONDS.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("run...");
                }
            },"t1").start();
    
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(()->{
                flag.set(true);
            },"t2").start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    如何停止一个运行中的线程???

    API方法说明
    public void interrupt()实例方法interrupt()仅仅是设置线程的中断状态为true,不会停止线程
    public static boolean interrupted()静态方法,Thread.interrupted();判断线程是否被中断,并清除当前中断状态
    public boolean isInterrupted()实例方法,判断当前线程是否被中断(通过检查中断标志位)
    中断一个运行线程 & interrupt & isInterrupted
    /**
     * 中断一个运行线程 & interrupt & isInterrupted
     */
    public class InterruptThreadTest01 {
    
    
        public static void main(String[] args) {
            Thread t1 = new Thread(() -> {
                while (true) {
                    if (Thread.currentThread().isInterrupted()) { //返回打断标识符true or false
                        System.out.println("stop...");
                        break;
                    }
                    System.out.println("run...");
                }
            }, "t1");
            t1.start();
    
            try {
                TimeUnit.MILLISECONDS.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(()->{
                t1.interrupt(); //将t1打断标识符置为true,并不会立即中断线程运行
            },"t2").start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    中断一个运行线程 & interrupt & isInterrupted
    • 当线程处于 sleep | wait | join 方法时中断会 清除中断标识符,并抛出中断异常
    • 解决方法:在 cathy块中重新打断 interrupt
    /**
     * 中断一个运行线程 & interrupt & isInterrupted
     * 当线程处于 sleep | wait | join 方法时中断会 清除中断标识符,并抛出中断异常
     * 解决方法:在 cathy块中重新打断 interrupt
     */
    public class InterruptThreadTest02 {
    
    
        public static void main(String[] args) {
            Thread t1 = new Thread(() -> {
                while (true) {
                    if (Thread.currentThread().isInterrupted()) { //返回打断标识符true or false
                        System.out.println("stop...");
                        break;
                    }
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();//重新打断,否则不会中断线程运行
                        e.printStackTrace();
                    }
                    System.out.println("run...");
                }
            }, "t1");
            t1.start();
    
            try {
                TimeUnit.MILLISECONDS.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(()->{
                t1.interrupt(); //将t1打断标识符置为true,并不会立即中断线程运行
            },"t2").start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    中断一个运行线程 & Interrupted
    • 返回当前中断标识符 true or false,并重置中断标识符 (false)
    /**
     * 中断一个运行线程 & Interrupted
     * 返回当前中断标识符 true or false,并重置中断标识符 (false)
     */
    public class InterruptThreadTest03 {
    
    
        public static void main(String[] args) {
    
            System.out.println(Thread.interrupted());//false
    
            Thread.currentThread().interrupt(); //中断
    
            System.out.println(Thread.interrupted());//true
    
            System.out.println(Thread.interrupted());//false
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    线程间通信

    • 使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒线程
    • 使用JUC包中Condition的await()方法让线程等待,使用signal()方法唤醒线程
    • LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程
    Object类中的wait和notify方法实现线程等待和唤醒
    • wait和notify方法必须要在同步块或者方法里面,且成对出现使用
    • 先wait后notify才OK
    /**
     * wait() & notify() & notifyAll()
     */
    public class WaitNotifyTest {
    
    
        public static void main(String[] args) {
    
            Object lock = new Object();
    
            new Thread(()->{
                synchronized (lock){
                    System.out.println("run...");
                    try {
                        lock.wait(); //wait,释放锁并进入等待队列
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("被唤醒。。。");
                }
            },"t1").start();
    
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(()->{
                synchronized (lock){
                    lock.notify(); //唤醒等待队列中的一个线程
                }
            },"t1").start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    使用JUC包中Condition的await()方法让线程等待,使用signal()方法唤醒线程
    • Condtion中的线程等待和唤醒方法之前,需要先获取锁
    • 一定要先await后signal
    /**
     * ReentrantLock
     * await() & signal() & signalAll()
     */
    public class AwaitSignalTest {
    
    
        public static void main(String[] args) {
    
            ReentrantLock lock = new ReentrantLock();
            Condition waitQueue = lock.newCondition();
    
            new Thread(()->{
                lock.lock(); //获得锁
                try {
                    System.out.println("run...");
                    try {
                        waitQueue.await(); //await,释放锁并进入等待队列
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("被唤醒。。。");
                } finally {
                    lock.unlock(); //释放锁
                }
            },"t1").start();
    
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(()->{
                lock.lock();
                try {
                    waitQueue.signal(); //唤醒等待队列中的一个线程
                } finally {
                    lock.unlock();
                }
            },"t1").start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程

    LockSupport类使用了一种名为Permit(许可)的概念来做到阻塞和唤醒线程的功能, 每个线程都有一个许可(permit), permit只有两个值1和零,默认是零。 可以把许可看成是一种(0,1)信号量(Semaphore),但与 Semaphore 不同的是,许可的累加上限是1。

    /**
     * LockSupport
     * park() & unpark()
     * 许可证数量只能是1,不可累加
     */
    public class LockSupportTest {
    
        public static void main(String[] args) {
    
            Thread t1 = new Thread(() -> {
    
                System.out.println("run...");
    
                LockSupport.park(); //获得许可证,无将被阻塞
    
                System.out.println("被唤醒。。。");
    
            }, "t1");
            t1.start();
    
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(()->{
                LockSupport.unpark(t1); //给线程t1发放许可证
            },"t1").start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  • 相关阅读:
    Linux项目实训一
    2015年经过官方去噪的NPP/VIIRS数据
    go工具类的封装——(一)配置文件工具类封装
    Golang Type关键字
    同态加密:以CKKS为例的Bootstrapping操作介绍(不定期更新)
    C语言再学习-002-+-*/><……
    Unity3D中实现Player的第一人称视角
    SpringBoot+Jwt+Redis
    内存取证入门第二题
    javascript设计模式单例
  • 原文地址:https://blog.csdn.net/qq_54429571/article/details/127696492