java中的单例模式、多线程交替打印、实现死锁及数组蓄水问题

1.饿汉式线程安全的单例模式

//饿汉式线程安全——单例模式
public class Singleton {
    //定义本类的一个私有实例对象
    private  static volatile  Singleton single = null;
    //私有化构造
    private Singleton() {}
    //因为不能创建对象,对外提供静态方法
    public static Singleton getSingleton() {
       if(single == null) {//先判断是否创建该类的单例对象single
           synchronized(Singleton.class) {
               /*可能多个线程都同时进行第一层if判断在锁外面等待,当一个线程创建完成释放锁后,
                * 如果不加判断则会导致再次创建对象
                */
               if(single == null) {
                  single = new Singleton();
               }
           }
       }
       return single;
    }
}

2.多线程实现两个线程交替打印20以内的数

//线程交替打印
public class ThreadPrint {
    public static void main(String[] args) {
       ThreadCase one = new ThreadCase();
       Thread t1 = new Thread(one);
       Thread t2 = new Thread(one);
       t1.start();
       t2.start();
    }
}
class ThreadCase implements Runnable{
    public int num = 0;//线程共享资源变量
    @Override
    public void run() {
           for(;num<=20;num++) {
               synchronized (this) {
               notify();//每次进来先唤醒等待的线程
               System.out.println(Thread.currentThread().getName()+":"+num);
               try {
                  Thread.sleep(1000);
                  if(num!=20) {//不加判断,程序打印完一直处于等待状态
                      wait();//每个线程执行打印后等待,让下一个线程进入
                  }
               } catch (InterruptedException e) {
                  e.printStackTrace();
               }
           }
       }
    }
}

3.实现死锁程序

/**示例:死锁*/
class ZhangSan{
    public void say() {
       System.out.println("张三说:你给我书,我就给你画");
    }
    public void get() {
       System.out.println("张三 获得了书");
    }
}
class Lisi{
    public void say() {
       System.out.println("李四:你给我画,我就给你书");
    }
    public void get() {
       System.out.println("李四获得了画");
    }
}
class DeadLockThread implements Runnable{
    private static ZhangSan zhangSan = new ZhangSan();
    private static Lisi lisi = new Lisi();
    public boolean tag = false;//标志量,保证张三和李四进入对应的条件分支
    @Override
    public void run() {
       if(tag == true) {//张三
           synchronized (zhangSan) {
               zhangSan.say();
               try {
                  Thread.sleep(1000);
               } catch (InterruptedException e) {
                  e.printStackTrace();
               }   
               synchronized (lisi) {
                  zhangSan.get();
               }
           }
       }else {//李四
           synchronized (lisi) {
               lisi.say();
               try {
                  Thread.sleep(1000);
               } catch (InterruptedException e) {
                  e.printStackTrace();
               }
               synchronized (zhangSan) {
                  lisi.get();
               }
           }
       }
    }
}
//测试死锁
public class DeadLock {
    public static void main(String[] args) {
       DeadLockThread td1 = new DeadLockThread();
       td1.tag = true;
       DeadLockThread td2 = new DeadLockThread();
       td2.tag = false;
       Thread t1 = new Thread(td1);
       Thread t2 = new Thread(td2);
       t1.start();
       t2.start();
    }
}

4.数组蓄水问题

java中的单例模式、多线程交替打印、实现死锁及数组蓄水问题_第1张图片

问题分析:

对于每个柱子,找到其左右两边最高的柱子,该柱子能容纳的面积就是min(max_left, max_right) - height,这个是问题的本质所在,理解了这个下面的方法就容易理解了

//数组蓄水问题
public class StorageArray {
    /**
     * 先找到数组中的最高点。该点将数组分为左右两半。对于左半侧,从左向右处理;对于右半侧,从右向左处理。
     * 处理的时候只需考虑已扫描一侧的高度即可,因另一侧有数组最高点,无需担心蓄水问题。
     * 该方法的时间复杂度O(N),空间复杂度O(1)
     * @param arr:求蓄水量的数组
     */
    public static int storageArray(int[] arr) {
       int maxPointIndex = 0;//数组中的最高点
       //先查找数组的最高点的索引
       for (int i = 1; i < arr.length; i++)
           if (arr[i] > arr[maxPointIndex])
               maxPointIndex = i;
       //声明该数组的蓄水量water
       int water = 0;
       //计算最高点左边的蓄水量
       for (int i = 1, leftMovePointIndex = 0; i < maxPointIndex; i++) {
           //如果左边相邻的两个位置,靠后的位置比前面位置的值大,则向后移动一位再次比较
           if (arr[i] > arr[leftMovePointIndex]) {
               leftMovePointIndex = i;
           } else {
               //靠后的位置比前面位置的值小,则证明可以积水,该蓄水量就是两个位置的之差
               water += arr[leftMovePointIndex] - arr[i];
           }
       }
       //计算最高点右边的蓄水量,跟左边的逻辑一样
       for (int i = arr.length - 2, rightMovePointIndex = arr.length - 1; i > maxPointIndex; i--) {
           if (arr[i] > arr[rightMovePointIndex])
               rightMovePointIndex = i;
           else
               water += arr[rightMovePointIndex] - arr[i];
       }
       //最终返回总的蓄水量
       return water;
    }
    //测试
    public static void main(String[] args) {
       int[] arr = {3,1,2,5,2,1,3};
       System.out.println("该数组下雨蓄水量为:"+storageArray(arr));
    }
}

 java中的单例模式、多线程交替打印、实现死锁及数组蓄水问题_第2张图片

你可能感兴趣的:(java,单例模式,数组蓄水,死锁,多线程交替打印)