如题,有两个线程A、B,A线程向一个集合(List<String>)中依次添加元素“abc”字符串,一共添加10次,当添加到第五次后,希望B线程能接收到A线程的通知,然后B线程执行相关的业务操作,我们应该如何进行设计?
解析:这道题很简单,设计两个线程,A线程for循环添加10次“abc”,B线程获取list的size,当长度为5时,执行业务逻辑,而不对A线程产生影响。
解题方式(一)
利用CountDownLanch ,通过计数实现线程之间的通信:
CountDownLanch.countDown();向下传递通知
CountDownLanch.await();等待,获取通知后立刻被唤醒
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class MyList {
//集合存储“abc”字符串
private List<String> list = new ArrayList<>();
//向list集合中添加元素
private void add() {
list.add("abc");
System.err.println("添加元素abc");
}
//获取list长度
private int getSize() {
return list.size();
}
public static void main(String[] args) {
MyList mList = new MyList();
//定义CountDownLanch
CountDownLatch cdl = new CountDownLatch(1);
Thread A = new Thread(new Runnable() {
@Override
public void run() {
try {
for(int i = 0;i< 10 ;i++) {
Thread.sleep(500);
mList.add();
if(mList.getSize() == 5) {
//向下传递通知
cdl.countDown();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A");
Thread B = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
//当集合长度小于5时,等待
if(mList.getSize() != 5) {
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.err.println("线程B收到通知,开始执行业务逻辑。。。");
System.err.println("线程B执行业务逻辑结束。。。");
break;
}
}
},"B");
B.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
A.start();
}
}
解题方式(二)
利用volatile关键字修饰,list集合作为共享数据,可以用volatile修饰
import java.util.ArrayList;
import java.util.List;
public class MyList {
//集合存储“abc”字符串
private volatile List<String> list = new ArrayList<>();
//向list集合中添加元素
private void add() {
list.add("abc");
System.err.println("添加元素abc");
}
//获取list长度
private int getSize() {
return list.size();
}
public static void main(String[] args) {
MyList mList = new MyList();
Thread A = new Thread(new Runnable() {
@Override
public void run() {
try {
for(int i = 0;i< 10 ;i++) {
Thread.sleep(500);
mList.add();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A");
Thread B = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
//当集合长度等于5时,执行业务逻辑
if(mList.getSize() == 5) {
System.err.println("线程B收到通知,开始执行业务逻辑。。。");
System.err.println("线程B执行业务逻辑结束。。。");
break;
}
}
}
});
B.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
A.start();
}
}
两种方式的结果都是: