【Java并发编程学习】3-线程挂起、恢复和终止

/**
 * 通过休眠来延缓运行,模拟长时间运行的情况,使线程更可能在不适当的时候被挂起
 * 说明:如果在不合适的时候挂起线程(如锁定共享资源时),此时便可能会发生死锁条件--其它线程在等待该线程释放锁,
 * 但该线程却被挂起,便会发生死锁。
 */
public class DeprecatedSuspendResume extends Object implements Runnable{
    private volatile int firstVal;
    private volatile int secondVal;

    public boolean areValuesEqual() {
        return (firstVal == secondVal);
    }

    @Override
    public void run() {
        try {
            firstVal  = 0;
            secondVal = 0;
            workMethod();
        } catch (InterruptedException e) {
            System.out.println("[DeprecatedSuspendResume] interrupted while in workMethod()");
        }
    }

    private void workMethod() throws InterruptedException {
        int val = 1;
        while (true) {
            /**
             * 若设置firstVal之后,但在设置secondVal之前,挂起新线程会产生麻烦
             */
            stepOne(val);
            stepTwo(val);
            val++;
            // 再次循环前休眠200 ms
            Thread.sleep(200);
        }
    }

    /**
     * 赋值后,休眠300ms,从而使线程有机会在stepOne()和stepTwo()之间被挂起
     */
    private void stepOne(int newVal) throws InterruptedException {
        firstVal = newVal;
        // 模拟长时间运行的情况
        Thread.sleep(300);
    }

    private void stepTwo(int newVal) {
        secondVal = newVal;
    }

    public static void main(String[] args) {
        DeprecatedSuspendResume dsr = new DeprecatedSuspendResume();
        Thread thread = new Thread(dsr);
        thread.start();
        // 休眠1 s,让其它线程有机会获得执行
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 10; i++) {
           // 挂起线程
           thread.suspend();
           System.out.println("[DeprecatedSuspendResume] dsr.areValuesEqual() = " + dsr.areValuesEqual()
           + " [main]= " + Thread.currentThread().getId() + " [thread]=" + thread.getId());
           // 恢复线程
           thread.resume();
           try {
               // 线程随机休眠0~2 s
            Thread.sleep((long)(Math.random()*2000.0));
           } catch (InterruptedException e) {

           }
        }
        // 中断应用程序
        System.exit(0);
    }
}
/**
 * 实现线程挂起和恢复的策略--设置标志位,可以在线程的指定位置实现线程的挂起和恢复,而不用担心其不确定性。
 */
public class AlternateSuspendResume extends Object implements Runnable {
    private volatile int firstVal;
    private volatile int secondVal;
    /**
     * 增加标志位,用来实现线程的挂起和恢复
      */
    private volatile boolean suspended;
    public boolean areValuesEqual() {
        return (firstVal == secondVal);
    }

    @Override
    public void run() {
        try {
            suspended = false;
            firstVal  = 0;
            secondVal = 0;
            workMethod();
        } catch (InterruptedException e) {
            System.out.println("[AlternateSuspendResume] interrupted while in workMethod()");
        }
    }

    private void workMethod() throws InterruptedException {
        int val = 1;
        while (true) {
            // 仅当线程挂起时,才运行这行代码
            waitWhileSuspended();
            stepOne(val);
            stepTwo(val);
            val++;
            // 仅当线程挂起时,才运行这行代码
            waitWhileSuspended();
            Thread.sleep(200);
        }
    }

    private void stepOne(int newVal) throws InterruptedException {
        firstVal = newVal;
        Thread.sleep(300);
    }

    private void stepTwo(int newVal) {
        secondVal = newVal;
    }

    public void suspendRequest() {
        suspended = true;
    }

    public void resumeRequest() {
        suspended = false;
    }

    private void waitWhileSuspended() throws InterruptedException {
        // 这是一个“繁忙等待”技术的示例
        while (suspended) {
            Thread.sleep(200);
        }
    }

    public static void main(String[] args) {
        AlternateSuspendResume asr = new AlternateSuspendResume();
        Thread thread = new Thread(asr);
        thread.start();
        // 休眠1 s,让其它线程有机会获得执行
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        /**
         * 设置firstVal之后,但在设置secondVal之前,挂起新线程
         * 此处休眠目的是为了防止在执行asr.areValuesEqual()进行比较时,
         * 恰逢stepOne操作执行完,而stepTwo操作还没执行
         */
        try {
            Thread.sleep(350);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 10; i++) {
            asr.suspendRequest();

            System.out.println("[AlternateSuspendResume] asr.areValuesEqual()= " + asr.areValuesEqual()
            + "[main]= " + Thread.currentThread().getId() + "[thread]= " + thread.getId());
            asr.resumeRequest();
        }
        try {
            // 线程随机休眠0~2 s
            Thread.sleep((long)(Math.random() * 2000.0));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 退出应用程序
        System.exit(0);
    }
}

猜你喜欢

转载自my.oschina.net/u/3545495/blog/1809997
今日推荐