版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012292754/article/details/88751061
1 线程间通信
多个线程并发执行时, 在默认情况下CPU是随机切换线程的,如果我们希望他们有规律的执行, 就可以使用通信, 例如每个线程执行一次打印
1.1 如何通信
- 如果希望线程等待, 就调用wait()
- 如果希望唤醒等待的线程, 就调用notify();
- notify是随机唤醒一个线程
- notifyAll是唤醒所有线程
- 这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用
- 如果方法中没有同步锁,会有异常IllegalMonitorStateException
2 两个线程之间的通信
package threadtest;
public class Demo12 {
public static void main(String[] args) {
MyTask task = new MyTask();
new Thread() {
@Override
public void run() {
while (true) {
try {
task.task1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread() {
@Override
public void run() {
while (true) {
try {
task.task2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
class MyTask {
int flag = 1; // 执行任务1
public synchronized void task1() throws InterruptedException {
if (flag != 1) {
this.wait(); // 当前线程等待
}
System.out.println("1.银行信用卡自动还款任务....");
flag = 2;
this.notify(); // 唤醒其他线程
}
public synchronized void task2() throws InterruptedException {
if (flag != 2) {
this.wait();
}
System.out.println("2.自动利息结算任务。。。");
flag = 1;
this.notify();
}
}
3 三个线程的通信
package threadtest;
public class Demo12 {
public static void main(String[] args) {
MyTask task = new MyTask();
new Thread() {
@Override
public void run() {
while (true) {
try {
task.task1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread() {
@Override
public void run() {
while (true) {
try {
task.task2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread() {
@Override
public void run() {
while (true) {
try {
task.task3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
class MyTask {
int flag = 1; // 执行任务1
public synchronized void task1() throws InterruptedException {
if (flag != 1) {
this.wait(); // 当前线程等待
}
System.out.println("1.银行信用卡自动还款任务....");
flag = 2;
// this.notify(); // 唤醒随机线程
this.notifyAll();
}
public synchronized void task2() throws InterruptedException {
if (flag != 2) {
this.wait();
}
System.out.println("2.自动利息结算任务。。。");
flag = 3;
// this.notify(); // 唤醒随机线程
this.notifyAll();
}
public synchronized void task3() throws InterruptedException {
if (flag != 3) {
this.wait();
}
System.out.println("3.短信提醒。。。");
flag = 1;
// this.notify(); // 唤醒随机线程
this.notifyAll();
}
}
3.1 多线程通信问题
- JDK5之前无法唤醒指定的一个线程;
- 如果多个线程之间通信,需要使用
notifyAll()
通知所有的线程,用while
来反复判断条件;
4 线程通信的注意问题
- 在同步代码块中,用哪个对象锁,就用哪个对象锁调用
wait
方法
4.1 为什么 wait
方法和 notify
方法定义在 Object
类中?
- 因为锁对象可以是任意的,
Object
是所有的类的基类;
4.2 sleep
方法和 wait
方法的区别?
sleep
方法必须传入参数,参数就是时间,时间到了自动醒来;wait
方法可以传入参数,可以不传入参数。传入参数就是在参数的时间结束后等待,不传入参数就是直接等待;sleep
方法在同步函数或同步代码块中,不释放锁,睡着了也抱着锁;wait
方法在同步函数或者同步代码块中,释放锁;