• Java线程之间通讯(三)


    使用wait和notify方法实现了线程间的通讯,都是Object 类的方法,java所有的对象都提供了这两个方法

    1.wait和notify必须配合synchronized使用

    2.wait方法释放锁,notify方法不释放锁

    import java.util.ArrayList;
    import java.util.List;
    
    public class ListAdd1 {
        private volatile static List list = new ArrayList();
    
        public void add(){
            list.add("laoshi");
        }
        public int size(){
            return list.size();
        }
    
        public static void main(String[] args) {
    
            final ListAdd1 list1 = new ListAdd1();
    
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        for(int i = 0; i <10; i++){
                            list1.add();
                            System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
                            Thread.sleep(500);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "t1");
    
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    while(true){
                        if(list1.size() == 5){
                            System.out.println("当前线程收到通知:" + Thread.currentThread().getName() + " list size = 5 线程停止..");
                            throw new RuntimeException();
                        }
                    }
                }
            }, "t2");
    
            t1.start();
            t2.start();
        }
    }
    

      

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    /**
     * wait notfiy 方法,wait释放锁,notfiy不释放锁
     */
    public class ListAdd2 {
        private volatile static List list = new ArrayList();
    
        public void add(){
            list.add("laoshi");
        }
        public int size(){
            return list.size();
        }
    
        public static void main(String[] args) {
    
            final ListAdd2 list2 = new ListAdd2();
    
            // 1 实例化出来一个 lock
            // 当使用wait 和 notify 的时候 , 一定要配合着synchronized关键字去使用
            final Object lock = new Object();
    
            final CountDownLatch countDownLatch = new CountDownLatch(1);
    
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        synchronized (lock) {
                            for(int i = 0; i <10; i++){
                                list2.add();
                                System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
                                Thread.sleep(500);
                                if(list2.size() == 5){
                                    System.out.println("已经发出通知..");
                                    countDownLatch.countDown();
                                    lock.notify();
                                }
                            }
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                }
            }, "t1");
    
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (lock) {
                        if(list2.size() != 5){
                            try {
                                System.out.println("t2进入...");
                                 lock.wait();
                                countDownLatch.await();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
                        throw new RuntimeException();
                    }
                }
            }, "t2");
    
            t2.start();
            t1.start();
        }
    }
    

      

    import java.util.LinkedList;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class MyQueue {
        //1 需要一个承装元素的集合
        private LinkedList<Object> list=new LinkedList<Object>();
    
        //2 需要一个计数器
        private AtomicInteger count=new AtomicInteger(0);
    
        //3 需要制定上限和下限
        private final int minSize=0;
        private final int maxSize ;
    
        //4 构造方法
        public MyQueue(int size){
            this.maxSize = size;
        }
        //5 初始化一个对象 用于加锁
        private final Object lock=new Object();
    
        //put(anObject): 把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断,
        // 直到BlockingQueue里面有空间再继续.
        public void put(Object obj){
            synchronized (lock){
                while (count.get()==this.maxSize){
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //1 加入元素
                list.add(obj);
                //2.计数器累加
                count.incrementAndGet();
                //3 通知另外一个线程(唤醒)
                lock.notify();
                System.out.println("新加入的元素为:" + obj);
            }
        }
    
        //take: 取走BlockingQueue里排在首位的对象,若BlockingQueue为空,
        // 阻断进入等待状态直到BlockingQueue有新的数据被加入.
        public Object take(){
            Object ret=null;
            synchronized (lock){
                while (count.get()==this.minSize){
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //1 做移除元素操作
                ret=list.removeFirst();
                //2 计数器递减
                count.decrementAndGet();
                //3 唤醒另外一个线程
                lock.notify();
            }
            return ret;
        }
        public int getSize(){
            return this.count.get();
        }
    
        public static void main(String[] args) {
    
            final MyQueue mq = new MyQueue(5);
            mq.put("a");
            mq.put("b");
            mq.put("c");
            mq.put("d");
            mq.put("e");
    
            System.out.println("当前容器的长度:" + mq.getSize());
    
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    mq.put("f");
                    mq.put("g");
                }
            },"t1");
    
            t1.start();
    
    
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    Object o1 = mq.take();
                    System.out.println("移除的元素为:" + o1);
                    Object o2 = mq.take();
                    System.out.println("移除的元素为:" + o2);
                }
            },"t2");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            t2.start();
        }
    }
    

      ThreadLocal:线程局部变量,是一种多线程间并发访问变量的解决方案,与synchronized枷锁的方式不同,ThreadLocal完全不提供锁,使用以空间换时间的手段,为每个线程提供变量的独立副本,以保证线程安全。

    在高并发量或者竞争激烈的场景,使用ThreadLoacal可以一定程度少减少锁竞争。

    public class ConnThreadLocal {
        public static  ThreadLocal<String> th=new ThreadLocal<String>();
        public void setTh(String value){
            th.set(value);
        }
        public void getTh(){
            System.out.println(Thread.currentThread().getName() + ":" + this.th.get());
        }
        public static void main(String[] args) throws InterruptedException {
    
            final ConnThreadLocal ct = new ConnThreadLocal();
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    ct.setTh("张三");
                    ct.getTh();
                }
            }, "t1");
    
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                        ct.getTh();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "t2");
    
            t1.start();
            t2.start();
        }
    }

    单例模式:最常见的饥饿模式(直接实力化对象),懒汉模式(在调用方法时进行实例化对象)

    在多线程中考虑性能和线程安全问题使用

    dubble check instance

    static inner class

    public class DubbleSingleton {
        private static  DubbleSingleton ds;
        public static  DubbleSingleton getDs(){
            if(ds == null){
                try {
                    //模拟初始化对象的准备时间...
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (DubbleSingleton.class) {
                    if(ds == null){
                        ds = new DubbleSingleton();
                    }
                }
            }
            return ds;
        }
        public static void main(String[] args) {
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(DubbleSingleton.getDs().hashCode());
                }
            },"t1");
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(DubbleSingleton.getDs().hashCode());
                }
            },"t2");
            Thread t3 = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(DubbleSingleton.getDs().hashCode());
                }
            },"t3");
    
            t1.start();
            t2.start();
            t3.start();
        }
    }
    

      这种方法用的多

    public class Singletion {
    
        private static class InnerSingletion {
            private static Singletion single = new Singletion();
        }
    
        public static Singletion getInstance(){
            return InnerSingletion.single;
        }
    }
    

      

    import java.util.concurrent.TimeUnit;
    
    public class Demo3 {
    	private volatile int signal;
        public synchronized void set(int value){
        	signal=1;
        	notifyAll(); //notifyAll叫醒所有的处于wait线程,争夺到时间片的线程只有一个
        	notify(); //notify方法会随机叫醒一个处于wait状态的线程
        	//notify 拿到锁
        	//this.signal=value;
        }
        public synchronized int get(){
        	System.out.println(Thread.currentThread().getName()+"方法执行了。。。");
        	if(signal!=1){
        		try {
    				wait(); //释放锁
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
        	}
        	System.out.println(Thread.currentThread().getName()+"方法执行完毕。。。");
        	return signal;
        }  
        public static void main(String[] args) {
    		Demo3 demo=new Demo3();
    		Target t1=new Target(demo);
    		Target t2=new Target(demo);
    		new Thread(t2).start();
    		new Thread(t2).start();
    		new Thread(t2).start();
    		new Thread(t2).start();
    		
    		try {
    			TimeUnit.SECONDS.sleep(1);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		new Thread(t1).start();
    	}
    }
    

      

  • 相关阅读:
    用U3D寻找看电视的感觉!!
    MipMap
    什么是 A 轮融资?有 B轮 C轮么?
    Java写的斗地主游戏源码
    sqlserver sp_spaceused用法
    SQL中的全局变量和局部变量(@@/@)
    SQL2008数据库导出到SQL2000全部步骤过程
    生成Insert语句的存储过程
    物理机连接虚拟机数据库
    配置sql server 2000以允许远程访问
  • 原文地址:https://www.cnblogs.com/sunliyuan/p/10840371.html
Copyright © 2020-2023  润新知