Q
为什么要学习多线程通信?
A
每个线程的内部有自己的私有的线程上线文,线程之间互不干扰。为了更好的利用服务器资源,我们通常需要多个线程之间进行协作。
业务目标,A、B两个线程依次输出
package co.dianjiu.thread;
public class MyThreadNoLock {
static class MyThreadA implements Runnable{
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("MyThreadA===>" + i);
}
}
}
static class MyThreadB implements Runnable{
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("MyThreadB===>" + i);
}
}
}
public static void main(String[] args) {
new Thread(new MyThreadA()).start();
new Thread(new MyThreadB()).start();
}
}
执行结果
A和B两个线程执行顺序无法控制
…
MyThreadB===>48
MyThreadA===>41
MyThreadB===>49
MyThreadA===>42
MyThreadA===>43
MyThreadA===>44
MyThreadA===>45
MyThreadA===>46
MyThreadA===>47
MyThreadA===>48
MyThreadA===>49
一、使用锁进行线程通信
根据线程和锁的关系,同一时间只有一个线程持有锁。
package co.dianjiu.thread;
public class MyThreadNoLock {
private static Object lock = new Object();
static class MyThreadA implements Runnable{
@Override
public void run() {
//对象锁,同步代码块
synchronized (lock){
for (int i = 0; i < 50; i++) {
System.out.println("MyThreadA===>" + i);
}
}
}
}
static class MyThreadB implements Runnable{
@Override
public void run() {
//对象锁,同步代码块
synchronized (lock){
for (int i = 0; i < 50; i++) {
System.out.println("MyThreadB===>" + i);
}
}
}
}
public static void main(String[] args) {
new Thread(new MyThreadA()).start();
new Thread(new MyThreadB()).start();
}
}
执行结果
可以控制A先执行、然后B在执行,距离目标更近了一些
…
MyThreadA===>47
MyThreadA===>48
MyThreadA===>49
MyThreadB===>0
MyThreadB===>1
MyThreadB===>2
MyThreadB===>3…
二、使用等待通知进行通信
等待通知机制建立的基础是两个线程使用了同一个对象锁,A、B两个线程先打印自己的输出后,唤醒另一个等待的线程,然后自己进入等待状态,同时释放锁。
package