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

线程停止、中断

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

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

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

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();
    }
}
中断一个运行线程 & 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();
    }
}
中断一个运行线程 & 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

    }
}

线程间通信

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

你可能感兴趣的:(Java,java)