【Java多线程编程核心技术】第一章(多线程技能suspend,resume,yield)

1.8 暂停线程

     在多线程中,suspend是暂停线程,resume是恢复线程的执行.

 1.8.1suspend方法和resume方法的使用

public class MyThread extends Thread {
    private long i = 0L;
    public long getI() {
        return i;
    }
    public void setI(long i) {
        this.i = i;
    }
    @Override
    public void run() {
        while(true) {
            i++;
        }
    }
    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep(5000);
            // A段
            thread.suspend();
            System.out.println("A= " + System.currentTimeMillis()+" i=" + thread.getI());
            Thread.sleep(5000);
            System.out.println("A= " + System.currentTimeMillis()+" i=" + thread.getI());
            // B段
            thread.resume();
            Thread.sleep(5000);
            // C段
            thread.suspend();
            System.out.println("B= " + System.currentTimeMillis()+" i=" + thread.getI());
            Thread.sleep(5000);
            System.out.println("B= " + System.currentTimeMillis()+" i=" + thread.getI());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

1.8.2 suspend与resume方法的缺点-独占

   在使用suspend与resume方法时,如果使用不当,极易造成公共的同步对象的独占,使得其它线程无法访问公共同步对象

public class SynchronizeObj {
    synchronized public void printString() {
        System.out.println("begin");
        if(Thread.currentThread().getName().equals("a")) {
            System.out.println("a 线程永远suspend..");
            Thread.currentThread().suspend();
        }
        System.out.println("end");
    }

    public static void main(String[] args) {
        try {
            final SynchronizeObj obj = new SynchronizeObj();
            Thread thread1 = new Thread(()->obj.printString());
            thread1.setName("a");
            thread1.start();
            Thread.sleep(500);

            Thread thread2 = new Thread(()->{
                System.out.println("thread2 启动了, 但是进入不了printString,只打印一个begin");
                System.out.println("因为printString方法被a线程锁定并且永远suspend暂停了");
                obj.printString();
            });
            thread2.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

还有另外一种独占锁的情况也要格外注意,稍有不慎,就会掉进坑里

public class MyThread extends Thread {
    private long i = 0L;
    public long getI() {
        return i;
    }
    public void setI(long i) {
        this.i = i;
    }
    @Override
    public void run() {
        while(true) {
            i++;
        }
    }
    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep(500);
            thread.suspend();
            System.out.println("main end");// 打印,但程序一直阻塞中
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

将run方法的代码修改如下:

    @Override
    public void run() {
        while(true) {
              i++;
              System.out.println(i);
        }
    }

再次运行发现,i被打印,但是不再打印main end,原因是当程序运行到println方法内部停止时,同步锁未被释放.源码如下

   /**
     * Prints a long and then terminate the line.  This method behaves as
     * though it invokes <code>{@link #print(long)}</code> and then
     * <code>{@link #println()}</code>.
     *
     * @param x  a The <code>long</code> to be printed.
     */
    public void println(long x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }

1.8.3 suspend与resume方法的缺点-不同步

   在使用suspend与resume方法也容易出现因为线程的暂停而导致数据不同步的情况. 

public class NoSameValue {

    private String username = "1";
    private String password = "11";

    public void setValue(String u, String p) {
        this.username = u;
        if (Thread.currentThread().getName().equals("a")) {
            System.out.println("stop thread A");
            Thread.currentThread().suspend();
        }
        this.password = p;
    }

    public void printUsernameAndPassword() {
        System.out.println(username + ":" + password);
    }

    public static void main(String[] args) {
        try {
            final NoSameValue obj = new NoSameValue();
            Thread thread1 = new Thread(() -> obj.setValue("a", "aa"));
            thread1.setName("a");
            thread1.start();
            Thread.sleep(500);
            new Thread(()->obj.printUsernameAndPassword()).start();// a:11
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

1.9 yield方法

yield方法的作用是放弃当前的cpu资源,将它让给其它的任务去占用cpu执行时间,但放弃的时间不确定,有可能刚刚放弃,马上又获得cpu时间片

public class YieldThread extends Thread{
    @Override
    public void run() {
        long beginTime = System.currentTimeMillis();
        int count = 0;
        for(int i=0; i<50000000; i++) {
//            Thread.yield();// 将cpu让给其它资源导致速度变慢
            count = count + (i+1);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("total time is " +(endTime - beginTime)+ " millisecond");// 21/ yield 17223
    }
    public static void main(String[] args) {
        new YieldThread().start();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值