什么时候需要通信?

多个线程并发执行是,在默认情况下CPU是随机切换线程的,如果我们希望他们有规律的执行,就可以使用通信,例如每个线程执行一次打印。

怎么通信?

1.如果希望线程等待,就调用wait()
2.如果希望唤醒等待的线程,就用notify()
3.这两个方法必须在同步代码中执行,并且使用同步锁对象来调用;如果方法没有同步锁,就会报错。

1.两个线程间的通信,轮流打印两个线程

public static void main(String[] args){
//创建线程任务
MyTask task=new MyTask();
//开启两个线程执行两个任务
new Thread(){
public void run(){
while(true){
try{
task.task1();
}catch(InterruptedException e){
e.printStackTrace();
}
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
}
};
}.start();

new Thread(){
public void run(){
while(true){
try{
task.task2();
}catch(InterruptedException e){
e.printStackTrace();
}
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
}
};
}.start();

new Thread(){
public void run(){
while(true){
try{
task.task3();
}catch(InterruptedException e){
e.printStackTrace();
}
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
}
};
}.start();
}

class MyTask(){
//标识,1可以执行任务1,2可以执行任务2
int flag=1;
public synchronized void task() throws InterruptedException{
if(flag!=1){
this.wait();//当前线程等待
}
System.out.println("1.银行信用卡自动还款业务...");
flag=2;
this.notify();//唤醒其他线程
}
public synchronized void task() throws InterruptedException{
if(flag!=2){
this.wait();//当前线程等待
}
System.out.println("1.银行信用卡自动还款业务...");
flag=1;
this.notify();//唤醒其他线程
}
}

2.三个线程之间的通信, 三个线程轮流打印

public static void main(String[] args){
//创建线程任务
MyTask task=new MyTask();
//开启两个线程执行两个任务
new Thread(){
public void run(){
while(true){
try{
task.task1();
}catch(InterruptedException e){
e.printStackTrace();
}
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
}
};
}.start();

new Thread(){
public void run(){
while(true){
try{
task.task2();
}catch(InterruptedException e){
e.printStackTrace();
}
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
}
};
}.start();
}

class MyTask(){
//标识,1可以执行任务1,2可以执行任务2,3可以执行任务3
int flag=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=3;
this.notify();//唤醒其他线程
}
public synchronized void task3() throws InterruptedException{
if(flag!=3){
this.wait();//当前线程等待
}
System.out.println("1.银行短信提醒业务...");
flag=1;
this.notify();//唤醒其他线程
}
}

3.线程通信的问题

1.在同步代码块中,用哪个对象锁,就用哪个对象调用wait方法
2.为什么wait方法和notify方法定义在Object这类中?
因为锁对象可以说任意对象,Object是所有类的基类,所以wait方法和notify方法需要定义在Object这个类中。
3.sleep方法和wait方法的区别?
sheep方法必须传入参数,参数就是时间,时间到了自动醒来
wait方法可以传入参数也可以不用传入参数,传入参数就是在参数的时间结束后等待,不传入参数就是一直等待直到唤醒
sleep方法在同步函数或同步代码块中,不释放锁,睡着了也抱着锁睡
wait方法在同步函数或者同步代码块中,释放锁。