zoukankan      html  css  js  c++  java
  • 《Java多线程编程核心技术》读后感(四)

     

     

     

     

    将任意对象作为对象监视器

     

    synchronized同步代码块还支持任意对象,使用格式为synchronized(非this对象)

    package Second;
    
    public class Service {
    
        private String usernameParam;
        private String passwordParam;
      private String anyString =  new String();
        public void setUsernamePassword(String username, String password) {
            try {
                synchronized (anyString) {
                    System.out.println("线程名称为:" + Thread.currentThread().getName()
                            + "在" + System.currentTimeMillis() + "进入同步块");
                    usernameParam = username;
                    Thread.sleep(3000);
                    passwordParam = password;
                    System.out.println("线程名称为:" + Thread.currentThread().getName()
                            + "在" + System.currentTimeMillis() + "离开同步块");
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }
    package Second;
    
    public class ThreadA extends Thread {
        private Service service;
    
        public ThreadA(Service service) {
            super();
            this.service = service;
        }
    
        @Override
        public void run() {
            service.setUsernamePassword("a", "aa");
    
        }
    
    }
    package Second;
    
    public class ThreadB extends Thread {
    
        private Service service;
    
        public ThreadB(Service service) {
            super();
            this.service = service;
        }
    
        @Override
        public void run() {
            service.setUsernamePassword("b", "bb");
    
        }
    
    }
    package Second;
    
    public class Run {
    
        public static void main(String[] args) {
            Service service = new Service();
    
            ThreadA a = new ThreadA(service);
            a.setName("A");
            a.start();
    
            ThreadB b = new ThreadB(service);
            b.setName("B");
            b.start();
    
        }
    
    }

    package Second;
    
    public class Service {
    
        private String usernameParam;
        private String passwordParam;
        public void setUsernamePassword(String username, String password) {
            try {
                String anyString = new String();
                synchronized (anyString) {
                    System.out.println("线程名称为:" + Thread.currentThread().getName()
                            + "在" + System.currentTimeMillis() + "进入同步块");
                    usernameParam = username;
                    Thread.sleep(3000);
                    passwordParam = password;
                    System.out.println("线程名称为:" + Thread.currentThread().getName()
                            + "在" + System.currentTimeMillis() + "离开同步块");
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }

     

    package Second;
    
    public class Service {
    
        private String anyString = new String();
    
        public void a() {
            try {
                synchronized (anyString) {
                    System.out.println("a begin");
                    Thread.sleep(3000);
                    System.out.println("a   end");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        synchronized public void b() {
            System.out.println("b begin");
            System.out.println("b   end");
        }
    
    }
    package Second;
    
    public class ThreadA extends Thread {
        private Service service;
    
        public ThreadA(Service service) {
            super();
            this.service = service;
        }
    
        @Override
        public void run() {
            service.a();
    
        }
    
    }
    package Second;
    
    public class ThreadB extends Thread {
    
        private Service service;
    
        public ThreadB(Service service) {
            super();
            this.service = service;
        }
    
        @Override
        public void run() {
            service.b();
    
        }
    
    }
    package Second;
    
    public class Run {
    
        public static void main(String[] args) {
            Service service = new Service();
    
            ThreadA a = new ThreadA(service);
            a.setName("A");
            a.start();
    
            ThreadB b = new ThreadB(service);
            b.setName("B");
            b.start();
    
        }
    
    }

    由于对象监视器不同,所以运行结果就是异步的

    下面验证多个线程调用同一个方法是随机的

    package Second;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MyList {
    
        private List list = new ArrayList();
    
        synchronized public void add(String username) {
            System.out.println("ThreadName=" + Thread.currentThread().getName()
                    + "执行了add方法!");
            list.add(username);
            System.out.println("ThreadName=" + Thread.currentThread().getName()
                    + "退出了add方法!");
        }
    
        synchronized public int getSize() {
            System.out.println("ThreadName=" + Thread.currentThread().getName()
                    + "执行了getSize方法!");
            int sizeValue = list.size();
            System.out.println("ThreadName=" + Thread.currentThread().getName()
                    + "退出了getSize方法!");
            return sizeValue;
        }
    
    }
    package Second;
    
    public class MyThreadA extends Thread {
    
        private MyList list;
    
        public MyThreadA(MyList list) {
            super();
            this.list = list;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 100000; i++) {
                list.add("threadA" + (i + 1));
            }
        }
    
    }
    package Second;
    
    public class MyThreadB extends Thread {
    
        private MyList list;
    
        public MyThreadB(MyList list) {
            super();
            this.list = list;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 100000; i++) {
                list.add("threadB" + (i + 1));
            }
        }
    }
    package Second;
    
    public class Test {
    
        public static void main(String[] args) {
            MyList mylist = new MyList();
    
            MyThreadA a = new MyThreadA(mylist);
            a.setName("A");
            a.start();
    
            MyThreadB b = new MyThreadB(mylist);
            b.setName("B");
            b.start();
        }
    
    }

    下面展示多线程出现脏读的情况

    package Second;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MyOneList {
    
        private List list = new ArrayList();
    
        synchronized public void add(String data) {
            list.add(data);
        };
    
        synchronized public int getSize() {
            return list.size();
        };
    
    }
    package Second;
    
    public class MyService {
    
        public MyOneList addServiceMethod(MyOneList list, String data) {
            try {
                synchronized (list) {
                    if (list.getSize() < 1) {
                        Thread.sleep(2000);
                        list.add(data);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return list;
        }
    
    }
    package Second;
    
    public class MyThread1 extends Thread {
    
        private MyOneList list;
    
        public MyThread1(MyOneList list) {
            super();
            this.list = list;
        }
    
        @Override
        public void run() {
            MyService msRef = new MyService();
            msRef.addServiceMethod(list, "A");
        }
    
    }
    package Second;
    
    public class MyThread2 extends Thread {
    
        private MyOneList list;
    
        public MyThread2(MyOneList list) {
            super();
            this.list = list;
        }
    
        @Override
        public void run() {
            MyService msRef = new MyService();
            msRef.addServiceMethod(list, "B");
        }
    
    }
    package Second;
    
    public class Run {
    
        public static void main(String[] args) throws InterruptedException {
            MyOneList list = new MyOneList();
    
            MyThread1 thread1 = new MyThread1(list);
            thread1.setName("A");
            thread1.start();
    
            MyThread2 thread2 = new MyThread2(list);
            thread2.setName("B");
            thread2.start();
            
            Thread.sleep(6000);
            
            System.out.println("listSize=" + list.getSize());
    
        }
    
    }

    "脏读"出现了。出现的原因是两个线程以异步的方式返回list参数的size()大小。解决办法是“”同步化

    package Second;
    
    public class MyService {
    
        public MyOneList addServiceMethod(MyOneList list, String data) {
            try {
                synchronized (list) {
                    if (list.getSize() < 1) {
                        Thread.sleep(2000);
                        list.add(data);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return list;
        }
    
    }

    由于list参数对象在项目中是一份实例,是单例的,而且也正需要对list参数的getsize()方法做同步的调用,所以就对list参数进行同步处理

  • 相关阅读:
    ASP生成静态文件编码为UTF-8格式的HTML文件
    asp图片化电话号码,避免蜘蛛之类爬走用户隐私
    动态上传多个文件(asp)
    简单测试IIS下的UrlRewrite技术
    mac配置tomcat
    CSS盒子
    CSS
    HTML
    从java到python
    HTTP协议
  • 原文地址:https://www.cnblogs.com/Michael2397/p/7842248.html
Copyright © 2011-2022 走看看