• 正确运用synchronized和二次判断 实现多线程安全


    正确运用synchronized和二次判断 实现多线程安全,做出高效二符合预期的程序,特别是多个线程跑一个对象的时候,如下图所示: 
    在此输入图片描述

    测试代码如下: 
    特别注意if(shutdownRequested){ *部分不同的写法。

    不然就会输出与逻辑不符的现象: 
    如:

    runner—-false—-我没有关闭。。。

    runner—-true—-我没有关闭。。。

    runner—-true—-我关闭了=====»>


    package com.xue.gang.volatiler;

    import java.util.concurrent.CountDownLatch;

    import java.util.concurrent.ExecutorService;

    import java.util.concurrent.Executors;

    public class VolatileRunner{

    public static void main(String args[]) throws InterruptedException {
    
        int size=1000;
    
        CountDownLatch countDownLatch = new CountDownLatch(size);
        TomRunner tomRunner = new TomRunner(false,countDownLatch,"runner");
        ExecutorService executorService = Executors.newCachedThreadPool();
    
        for(int i=1;i<=size;i++){
            executorService.execute(new Thread2RunTomRunner(countDownLatch,tomRunner,i+"_号"));
        }
        countDownLatch.await();
        executorService.shutdown();
        //new Thread(volatileRunner).start();
    }
    
    static class Thread2RunTomRunner implements Runnable{
        private CountDownLatch  countDownLatch;
        private TomRunner tomRunner;
        private String name;
    
        public Thread2RunTomRunner(CountDownLatch countDownLatch,
                TomRunner tomRunner, String name) {
            super();
            this.countDownLatch = countDownLatch;
            this.tomRunner = tomRunner;
            this.name = name;
        }
    
        public void run() {
            System.out.println(this.name+":running...");
            this.tomRunner.doWork();
            System.out.println(this.name+":结束...");
            this.countDownLatch.countDown();
    
        }
    }
    static class TomRunner{
    
        volatile boolean shutdownRequested = false;
        //boolean shutdownRequested = false;
        String name;
    
        public TomRunner(boolean shutdownRequested,
                CountDownLatch countDownLatch, String name) {
            super();
            this.shutdownRequested = shutdownRequested;
    
            this.name = name;
        }
    
        public void shutdown() {
            this.shutdownRequested = true;
        }
        public void doWork() {
            while (true) {
    
                /**
                 *多个线程的代码去执行:  System.out.println(this.name + "----" + this.shutdownRequested +"----" +"我没有关闭。。。");
                 * */
                   /*if(shutdownRequested){
                        System.out.println(this.name + "----" + this.shutdownRequested +"----" +"我关闭了=====>>>");
                        break;
                    }else{
                        System.out.println(this.name + "----" + this.shutdownRequested +"----" +"我没有关闭。。。");
                        shutdown();
                    }*/
                /**
                 * 如果没有二次判断,也会出现比较脏数据.
                 * */
                /*
                    if(shutdownRequested){
                        System.out.println(this.name + "----" + this.shutdownRequested +"----" +"我关闭了=====>>>");
                        break;
                    }
                    synchronized (this) {
                        System.out.println(this.name + "----" + this.shutdownRequested +"----" +"我没有关闭。。。");
                        shutdown();
                    }*/
                /**
                 * 加上二次判断,能够正确
                 * */
    
                if(shutdownRequested){
                    System.out.println(this.name + "----" + this.shutdownRequested +"----" +"我关闭了=====>>>");
                    break;
                }
                    synchronized (this) {
                    if(!shutdownRequested){
                        System.out.println(this.name + "----" + this.shutdownRequested +"----" +"我没有关闭。。。");
                        shutdown();
                    }
                }           
            }
        }
    }
    

    }

    原:http://my.oschina.net/u/177808/blog/165442

  • 相关阅读:
    Win10以管理员身份运行Loadrunner11时候提示“管理员已阻止你运行此应用”
    logrotate日志切割
    Scala的型变
    Caused by: com.esotericsoftware.kryo.KryoException: Buffer overflow. Available: 0, required: 134217728
    ERROR BatchJobMain: Task not serializable
    Spark创建HiveContext报错tez的问题
    Spark初始换HiveContext空指针异常
    windows10专业版 操作系统无法监听远程端口
    windows环境如何上传项目到gitee
    canal-kakfa-flink实现mysql数据的实时同步(一)
  • 原文地址:https://www.cnblogs.com/langtianya/p/5128958.html
Copyright © 2020-2023  润新知