日度归档:2020年11月14日

Java多线程中的线程安全问题

多个线程访问共享数据就会产生冲突的问题,以卖票为例,多个窗口卖同一批票就会出现重复卖的问题

  public static void main(String[] args) {
      Runnable runnable = new Runnable() {
          Integer tickets = 100;
          @Override
          public void run() {
              String name = Thread.currentThread().getName();
              while(tickets-- > 0) {
                  try {
                      Thread.sleep(1);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  System.out.println(name + "正在卖票: " + tickets);
              }
          }
      };
      new Thread(runnable).start();
      new Thread(runnable).start();
      new Thread(runnable).start();
  }

解决方案一:使用同步机制,共享部分同步执行则不会出现重复操作问题

  1. synchronized关键字实现代码块同步
    public static void main(String[] args) {
        Object lock = new Object();
        Runnable runnable = new Runnable() {
            Integer tickets = 100;
    
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                while (true) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (lock) {
                        if (tickets <= 0) break;
                        System.out.println(name + "正在卖票: " + tickets);
                        tickets--;
                    }
                }
            }
        };
        new Thread(runnable).start();
        new Thread(runnable).start();
        new Thread(runnable).start();
    }
    
  2. synchronized同步方法实现同步机制
    static Integer tickets = 100;
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    sellTicked();
                    if (tickets <= 0) break;
                }
            }
        };
        new Thread(runnable).start();
        new Thread(runnable).start();
        new Thread(runnable).start();
    }
    
    synchronized private static void sellTicked() {
        if (tickets <= 0) return;
        String name = Thread.currentThread().getName();
        System.out.println(name + "正在卖票: " + tickets);
        tickets--;
    }
    

解决方案二:使用锁ReentrantLock
继续阅读

Java多线程的三种开启方式

  1. 继承自Thread重写run方法
     public class MyThread extends Thread {
    
         @Override
         public void run() {
             System.out.println(getName());
             String name = getName();
             for (int i = 0; i < 20; i++) {
                 System.out.println(name + "---" + i);
             }
         }
     }
    
  2. 实现Runable接口及run方法
     public class RunableImp implements Runnable {
    
         @Override
         public void run() {
             String name = Thread.currentThread().getName();
             for (int i = 0; i < 20; i++) {
                 System.out.println(name + "---" + i);
             }
         }
     }
    
  3. 匿名内部类实现run方法
     // Runable匿名
     Thread thread1 = new Thread(new Runnable() {
         @Override
         public void run() {
             String name = Thread.currentThread().getName();
             for (int i = 0; i < 20; i++) {
                 System.out.println(name + "---" + i);
             }
         }
     });
     thread1.start();
     // Thread匿名
     new Thread() {
         @Override
         public void run() {
             String name = Thread.currentThread().getName();
             for (int i = 0; i < 20; i++) {
                 System.out.println(name + "---" + i);
             }
         }
     }.start();
    

Java中集合的基本使用

  1. 数组与集合的基本区别:
  • 数组的长度是固定的,而集合的长度是可变的;
  • 数组可以存放任意数据类型,而集合不能存储基本数据类型;
  1. 集合(Collection)分为两大接口类:ListSet
  • List的实现类有ArrayListLinkedListVector
  • Set的实现类有HashSet(LinkedHashSet)、TreeSet
  1. Collection –> AbstractCollection –> AbstractList –> ArrayListtoString方法在AbstractCollection中被实现

  2. Iterator迭代器的使用

    ArrayList<Object> array = new ArrayList<>();
    array.add(1);
    array.add(2);
    array.add(3);
    // 使用迭代进行集合遍历
    Iterator iterator = array.iterator();
    while(iterator.hasNext()) {
       Object next = iterator.next();
       System.out.println(next);
    }
    System.out.println("-----------------------");
    // for循环实现
    for (Iterator it = array.iterator(); it.hasNext(); ) {
       System.out.println(it.next());
    }
    System.out.println("------------------------");
    // 增加for,所以实现Iterable接口的类都可以使用增强for进行遍历,底层实现通过iterator
    for (Object obj: array) {
       System.out.println(obj);
    }