关键:容器使用volatile关键字修饰。
方法一:
使用wait(),notify()实现。
package com.example.demo;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class Container {
//volatile关键字,使t2得到通知,否则t2不能判断container的size
volatile List<Object> list = new ArrayList<>();
public void add(Object o){
list.add(o);
}
public int getSize(){
return list.size();
}
public static void main(String[] args) {
Container container = new Container();
final Object lock = new Object();
new Thread(()->{
synchronized (lock){
System.out.println("t2启动");
if(container.getSize() != 5){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("t2结束");
//通知t1继续执行
lock.notify();
}
},"t2").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
synchronized (lock){
System.out.println("t1启动");
for(int i =0;i < 10;i++){
container.add(new Object());
System.out.println("add"+i);
if(container.getSize() == 5){
lock.notify();
try {
//释放锁,让t2可以获得锁得以执行
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"t1").start();
}
}
方法二:
使用Latch(门闩)代替wait,notify来进行通知
好处通信方式简单,同时也可以指定等待时间
使用await和countdown方法替代wait和notify
CountDownLatch不涉及锁定,当count的值为零时线程继续执行
当不涉及同步,只是涉及线程通信的时候,用synchronized + wait/notify就显得太重了
package com.example.demo;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class Container {
//volatile关键字,使t2得到通知,否则t2不能判断container的size
volatile List<Object> list = new ArrayList<>();
public void add(Object o){
list.add(o);
}
public int getSize(){
return list.size();
}
public static void main(String[] args) {
Container container = new Container();
//调用countDown方法后-1,门就开了
CountDownLatch latch = new CountDownLatch(1);
new Thread(()->{
System.out.println("t2启动");
if(container.getSize() != 5){
try {
latch.await();
//也可以指定等待时间
//latch.await(5,TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("t2结束");
},"t2").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
System.out.println("t1启动");
for(int i =0;i < 10;i++){
container.add(new Object());
System.out.println("add"+i);
if(container.getSize() == 5){
//打开门闩,让t2得以执行
latch.countDown();
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"t1").start();
}
}