我们通常在面试中大量遇到的手撕代码的题无非就是以下几种: 死锁,几种排序算法(最常考的快速排序,归并排序),生产者消费者模式,单例模式 在多线程这边,我们通常需要掌握生产者消费者模式,生产者消费者模式我们可以用sychronized版本写,更加高阶的可以用Reentranlock版本+condition(条件变量)来写。 为了达到精准通知的目的,我们还可以使用ReentrantLock版本+多个condition(条件变量来写)。
sychronized版本:
public class Demo01 { public static void main(String[] args) { Data data = new Data(); new Thread(()->{ for(int i =0;i<10;i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"线程A").start(); new Thread(()->{ for(int i =0;i<10;i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"线程B").start(); new Thread(()->{ for(int i =0;i<10;i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"线程C").start(); new Thread(()->{ for(int i =0;i<10;i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"线程D").start(); } } class Data{ private int number = 0;//定义初始数量为0 public synchronized void increment() throws InterruptedException { while(number !=0) { this.wait(); } number++; System.out.println(Thread.currentThread().getName()+"=>"+number); //通知其他线程,我自增完了 this.notifyAll(); } public synchronized void decrement() throws InterruptedException { while(number == 0) { this.wait(); } number--; System.out.println(Thread.currentThread().getName()+"=>"+number); //通知其他线程,我自增完了 this.notifyAll(); } }ReentrantLock +单个condition(条件变量版本)
public class Demo01 { public static void main(String[] args) { Data data = new Data(); new Thread(()->{ for(int i =0;i<10;i++) { data.increment(); } },"线程A").start(); new Thread(()->{ for(int i =0;i<10;i++) { data.decrement(); } },"线程B").start(); new Thread(()->{ for(int i =0;i<10;i++) { data.increment(); } },"线程C").start(); new Thread(()->{ for(int i =0;i<10;i++) { data.decrement(); } },"线程D").start(); } } class Data{ private int number = 0; //创建lock锁 Lock lock = new ReentrantLock(); //通过kock锁建立条件变量 Condition condition = lock.newCondition(); //+1 public void increment() { lock.lock(); try { //业务代码 while(number !=0) { condition.await(); } number++; System.out.println(Thread.currentThread().getName()+"=>"+number); //通知其他线程,我+1完毕了 condition.signalAll(); }catch(Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } //-1 public void decrement() { lock.lock(); try { //业务代码 while(number ==0) { condition.await(); } number--; System.out.println(Thread.currentThread().getName()+"=>"+number); //通知其他线程,我-1完毕了 condition.signalAll(); }catch(Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } }但是上述代码会出现一个问题,那就是通知的情况是随机性的,我们如果要达到精准通知的目的,我们需要用多个condition来达到精准通知的效果! ReentrantLock +多个condition(条件变量版本)
package RentrantLockDemo; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Demo02 { public static void main(String[] args) { Data03 data =new Data03(); new Thread(()->{ for(int i =0;i<10;i++) { data.printA(); } },"线程A").start(); new Thread(()->{ for(int i =0;i<10;i++) { data.printB(); } },"线程B").start(); new Thread(()->{ for(int i =0;i<10;i++) { data.printC(); } },"线程C").start(); } } class Data03{ //定义初始 的票数 private int number =1;//当为1的时候唤醒打印A,当为2的时候唤醒打印B,当为3的时候唤醒打印C private Lock lock = new ReentrantLock(); private Condition condition1 = lock.newCondition(); private Condition condition2 = lock.newCondition(); private Condition condition3 = lock.newCondition(); public void printA() { lock.lock(); try { //业务逻辑 while(number!=1) { condition1.await(); } System.out.println(Thread.currentThread().getName()+"=>AAAAAAAAAAA"); number =2; condition2.signal(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } public void printB() { lock.lock(); try { while(number!=2) { condition2.await(); } System.out.println(Thread.currentThread().getName()+"=>BBBBBBBBBBBB"); number =3; condition3.signal(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } public void printC() { lock.lock(); try { while(number!=3) { condition3.await(); } System.out.println(Thread.currentThread().getName()+"=>ccccccccc"); number =1; condition1.signal(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } }为了秋招更好的复习,所以会经常和大家分享一些平时的学习所得,如果有错误,也请大家指正!感谢大家!