线程同步一致性经典面试题

线程同步一致性经典面试题

 

如题,有两个线程A、B,A线程向一个集合(List) 里面依次添加元素“abc”字符串, 一共添加十次,当添加到第五次的时候,希望B线程能够收到A线程的通知,然后B线程执行相关的业务操作,我们应该如何进行设计?

 

实现方式1:采用volatile关键字

  • Volatile概念:Volatile关键字的主要作用是使共享变量在多个线程间可见。
  • 作用:
    • 在多线程间可以进行变量的变更,使得线程间进行数据的共享可见
    • 阻止指令重排序,happens-before

 

import java.util.ArrayList;

import java.util.List;



public class AddList {

    private volatile static  List list = new ArrayList<>();

    private static void add(){

        list.add("abc");

    }

    private static int getSize(){

        return list.size();

    }

    public static void main(String[] args){

        Thread t1 = new Thread(new Runnable() {

            @Override

            public void run() {

                for(int i=0;i<10;i++){

                        add();

                        System.out.println("线程" + Thread.currentThread().getName() + "执行了" + i + "次");

                    try {

                        Thread.sleep(100);

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }

                }

            }

        },"t1");

        Thread t2 = new Thread(new Runnable() {

            @Override

            public void run() {

                while(true) {

                        if (getSize() == 5) {

                            System.out.println("接收通知"+list.get(4));

                            throw new RuntimeException();

                        }

                    }

                }

        },"t2");

        t2.start();

        try {

            Thread.sleep(100);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        t1.start();

    }

}

 

实现方式2:使用wait / notify 方法实现线程间的通信,wait 和 notify 必须配合 synchronized 关键字使用

 

 

 

 

import java.util.ArrayList;

import java.util.List;



public class AddList {

    private static  List list = new ArrayList<>();

    private static void add(){

        list.add("abc");

    }

    private static int getSize(){

        return list.size();

    }

    public static void main(String[] args){

        Object lock = new Object();

        Thread t1 = new Thread(new Runnable() {

            @Override

            public void run() {

                for(int i=0;i<10;i++){

                    synchronized (lock) {

                        add();

                        System.out.println("线程" + Thread.currentThread().getName() + "执行了" + i + "次");

                        if (getSize() == 5) {

                            lock.notify();

                            System.out.println("发送通知" + list.get(4));

                        }

                    }

                }

            }

        },"t1");

        Thread t2 = new Thread(new Runnable() {

            @Override

            public void run() {

                while(true) {

                    synchronized (lock) {

                        if (getSize() != 5) {

                            try {

                                lock.wait();

                            } catch (InterruptedException e) {

                                e.printStackTrace();

                            }

                        }

                    }

                    System.out.println("接收通知"+list.get(4));

                    throw new RuntimeException();

                }

            }

        },"t2");

        t2.start();

        try {

            Thread.sleep(100);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        t1.start();

    }

}

 

实现方式3:使用CountDownLatch用于监听某些初始化操作,并且线程进行阻塞,等初始化执行完毕后,通知主线程继续工作执行

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.SynchronousQueue;



public class AddList {

    private static  List list = new ArrayList<>();

    private static void add(){

        list.add("abc");

    }

    private static int getSize(){

        return list.size();

    }

    public static void main(String[] args){

        final CountDownLatch latch = new CountDownLatch(1);

        Thread t1 = new Thread(new Runnable() {

            @Override

            public void run() {

                for(int i=0;i<10;i++){

                    add();

                    System.out.println("线程"+Thread.currentThread().getName()+"执行了"+i+"次");

                    if(getSize()==5){

                        latch.countDown();

                        System.out.println("发送通知"+list.get(4));

                    }

                }

            }

        },"t1");

        Thread t2 = new Thread(new Runnable() {

            @Override

            public void run() {

                while(true) {

                    if (getSize() != 5) {

                        try {

                            latch.await();

                        } catch (InterruptedException e) {

                            e.printStackTrace();

                        }

                    }

                    System.out.println("接收通知"+list.get(4));

                    throw new RuntimeException();

                }

            }

        },"t2");

        t2.start();

        try {

            Thread.sleep(100);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        t1.start();

    }

}

 

实现方式4:采用SynchronousQueue,一种没有缓冲的队列,生产者产生的数据直接会被消费者获取并消费

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.SynchronousQueue;



public class AddList {

    private static  List list = new ArrayList<>();

    private static void add(){

        list.add("abc");

    }

    private static int getSize(){

        return list.size();

    }

    public static void main(String[] args){

        SynchronousQueue queue = new SynchronousQueue<>();

        Thread t1 = new Thread(new Runnable() {

            @Override

            public void run() {

                for(int i=0;i<10;i++){

                    add();

                    System.out.println("线程"+Thread.currentThread().getName()+"执行了"+i+"次");

                    if(getSize()==5){

                        queue.add(list.get(i));

                        System.out.println("发送通知"+list.get(4));

                    }

                }

            }

        },"t1");

        Thread t2 = new Thread(new Runnable() {

            @Override

            public void run() {

                try {

                    if (queue.take() != null) {

                        System.out.println("接到通知"+list.get(4));

                    }

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        },"t2");

        t2.start();

        try {

            Thread.sleep(100);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        t1.start();

    }

}

你可能感兴趣的:(java并发编程)