使用 volatile 关键字
public class TestSync {
// 定义一个共享变量来实现通信,它需要是volatile修饰,否则线程不能及时感知
static volatile boolean notice = false;
public static void main(String[] args) {
List list = new ArrayList<>();
// 实现线程A
Thread threadA = new Thread(() -> {
for (int i = 1; i <= 10; i++) {
list.add("abc");
System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (list.size() == 5)
notice = true;
}
});
// 实现线程B
Thread threadB = new Thread(() -> {
while (true) {
if (notice) {
System.out.println("线程B收到通知,开始执行自己的业务...");
break;
}
}
});
// 需要先启动线程B
threadB.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 再启动线程A
threadA.start();
}
}
运行结果:
线程A向list中添加一个元素,此时list中的元素个数为:1
线程A向list中添加一个元素,此时list中的元素个数为:2
线程A向list中添加一个元素,此时list中的元素个数为:3
线程A向list中添加一个元素,此时list中的元素个数为:4
线程A向list中添加一个元素,此时list中的元素个数为:5
线程A向list中添加一个元素,此时list中的元素个数为:6
线程B收到通知,开始执行自己的业务...
线程A向list中添加一个元素,此时list中的元素个数为:7
线程A向list中添加一个元素,此时list中的元素个数为:8
线程A向list中添加一个元素,此时list中的元素个数为:9
线程A向list中添加一个元素,此时list中的元素个数为:10
Process finished with exit code 0
至于为什么个数为6时,才运行线程B,当list.size() == 5,notice变为true,线程A此时并未停止循环,而是再次执行了i=6的循环
使用Object类的wait() 和 notify() 方法
public class TestSync {
public static void main(String[] args) {
// 定义一个锁对象
Object lock = new Object();
List list = new ArrayList<>();
// 实现线程A
Thread threadA = new Thread(() -> {
synchronized (lock) {
for (int i = 1; i <= 10; i++) {
list.add("abc");
System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (list.size() == 5)
lock.notify();// 唤醒B线程
}
}
});
// 实现线程B
Thread threadB = new Thread(() -> {
while (true) {
synchronized (lock) {
if (list.size() != 5) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程B收到通知,开始执行自己的业务...");
}
}
});
// 需要先启动线程B
threadB.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 再启动线程A
threadA.start();
}
}
输出:
线程A向list中添加一个元素,此时list中的元素个数为:1
线程A向list中添加一个元素,此时list中的元素个数为:2
线程A向list中添加一个元素,此时list中的元素个数为:3
线程A向list中添加一个元素,此时list中的元素个数为:4
线程A向list中添加一个元素,此时list中的元素个数为:5
线程A向list中添加一个元素,此时list中的元素个数为:6
线程A向list中添加一个元素,此时list中的元素个数为:7
线程A向list中添加一个元素,此时list中的元素个数为:8
线程A向list中添加一个元素,此时list中的元素个数为:9
线程A向list中添加一个元素,此时list中的元素个数为:10
线程B收到通知,开始执行自己的业务...
线程A发出notify()唤醒通知之后,依然是走完了自己线程的业务之后,线程B才开始执行,这也正好说明了,notify()方法不释放锁
notify正确的使用方法:不要在notify后再执行业务代码
public class WaitNotify {
// 状态锁
private static Object lock = new Object();
private static Integer i = 0;
public void odd() {
while (i < 10) {
synchronized (lock) {
if (i % 2 == 1) {
System.out.println(Thread.currentThread().getName() + " - " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
lock.notify();
} else {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public void even() {
while (i < 10) {
synchronized (lock) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + " - " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
lock.notify();
} else {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) {
final WaitNotify waitNotify = new WaitNotify();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
waitNotify.odd();
}
}, "线程1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
waitNotify.even();
}
}, "线程2");
t1.start();
t2.start();
}
}
CountDownLatch
public class TestCountDown {
public static void main(String[] args) {
final CountDownLatch countDownLatch = new CountDownLatch(1);
final List list = new ArrayList<>();
// 实现线程A
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
list.add("abc");
System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (list.size() == 5)
countDownLatch.countDown();
}
}
});
// 实现线程B
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if (list.size() != 5) {
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程B收到通知,开始执行自己的业务...");
break;
}
}
});
// 需要先启动线程B
threadB.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 再启动线程A
threadA.start();
}
}
输出:
线程A向list中添加一个元素,此时list中的元素个数为:1
线程A向list中添加一个元素,此时list中的元素个数为:2
线程A向list中添加一个元素,此时list中的元素个数为:3
线程A向list中添加一个元素,此时list中的元素个数为:4
线程A向list中添加一个元素,此时list中的元素个数为:5
线程A向list中添加一个元素,此时list中的元素个数为:6
线程B收到通知,开始执行自己的业务...
线程A向list中添加一个元素,此时list中的元素个数为:7
线程A向list中添加一个元素,此时list中的元素个数为:8
线程A向list中添加一个元素,此时list中的元素个数为:9
线程A向list中添加一个元素,此时list中的元素个数为:10
Process finished with exit code 0
countDownLatch.countDown()执行-1操作,当count=0时,会通知countDownLatch.await(),继续执行下面代码
LockSupport
public class LockSupportTest {
public static void main(String[] args) {
final List list = new ArrayList<>();
// 实现线程B
final Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
if (list.size() != 5) {
LockSupport.park();
}
System.out.println("线程B收到通知,开始执行自己的业务...");
}
});
// 实现线程A
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
list.add("abc");
System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (list.size() == 5)
LockSupport.unpark(threadB);
}
}
});
threadA.start();
threadB.start();
}
}
输出:
线程A向list中添加一个元素,此时list中的元素个数为:1
线程A向list中添加一个元素,此时list中的元素个数为:2
线程A向list中添加一个元素,此时list中的元素个数为:3
线程A向list中添加一个元素,此时list中的元素个数为:4
线程A向list中添加一个元素,此时list中的元素个数为:5
线程A向list中添加一个元素,此时list中的元素个数为:6
线程B收到通知,开始执行自己的业务...
线程A向list中添加一个元素,此时list中的元素个数为:7
线程A向list中添加一个元素,此时list中的元素个数为:8
线程A向list中添加一个元素,此时list中的元素个数为:9
线程A向list中添加一个元素,此时list中的元素个数为:10
Process finished with exit code 0