线程间通讯:
多个线程在处理同一资源,但是任务却不同 。
比如对于同一个资源,一边在输入,一边在输出:
class Resource{
String name;
String sex;
}
//输入
class Input implements Runnable{
Resource r;
Input(Resource r){
this.r=r;
}
public void run(){
int x=0;
while(true){
synchronized(r){//因为Resource是共同操作的,所以r可以作为锁
if(x==0){
r.name="mike";
r.sex="nan";
}else{
r.name="丽丽";
r.sex="女女女女";
}
x=(x+1)%2;
}
}
}
}
//输出
class Output implements Runnable{
Resource r;
Output(Resource r){
this.r=r;
}
public void run(){
while(true){
synchronized(r){
System.out.print(r.name+"..."+r.sex);
}
}
}
}
public class TongXun {
public static void main(String[] args) {
//创建资源
Resource r=new Resource();
//创建任务
Input in=new Input(r);
Output out=new Output(r);
//创建线程,执行路径
Thread t1=new Thread(in);
Thread t2=new Thread(out);
//开启线程
t1.start();
t2.start();
}
}
运行:等待唤醒机制:
涉及的方法:
1 wait():让线程处于冻结状态,被wait的线程会被存储到线程池当中。
2 notify():唤醒线程池中的任意一个线程。
3 notifyAll():唤醒线程池中的所有线程
这些方法都必须定义在同步中。
因为这些方法是用于操作线程状态的方法。
必须要明确到底操作得是哪个锁上的线程。
class Resource{
String name;
String sex;
boolean flag=false;
}
//输入
class Input implements Runnable{
Resource r;
Input(Resource r){
this.r=r;
}
public void run(){
int x=0;
while(true){
synchronized(r){//因为Resource是共同操作的,所以r可以作为锁
if(r.flag)
try{
r.wait();
}catch(InterruptedException e){
}
if(x==0){
r.name="mike";
r.sex="nan";
}else{
r.name="丽丽";
r.sex="女女女女";
}
r.flag=true;
r.notify();
}
x=(x+1)%2;
}
}
}
//输出
class Output implements Runnable{
Resource r;
Output(Resource r){
this.r=r;
}
public void run(){
while(true){
synchronized(r){
if(!r.flag)
try{
r.wait();
}catch(InterruptedException e){
}
System.out.println(r.name+"..."+r.sex);
r.flag=false;
r.notify();
}
}
}
}
public class NofityDemo {
public static void main(String[] args) {
//创建资源
Resource r=new Resource();
//创建任务
Input in=new Input(r);
Output out=new Output(r);
//创建线程,执行路径
Thread t1=new Thread(in);
Thread t2=new Thread(out);
//开启线程
t1.start();
t2.start();
}
}
运行:等待唤醒机制避免了成片的输出的现象,因为等待唤醒机制做的就是当一个资源被输入,资源被占有,只有先输出了才能再次输入资源
思考1:wait(),notify(),notifyAll(),用来操作线程为什么定义在了Object类中?
1 这些方法存在于同步中;
2 使用这些方法时必须要标识所属的同步的锁。
3 锁可以是任意对象,所以任意对象调用的方法一定定义在Object类中。
优化:
资源一般都是私有的,这里资源进行私有化,并对外提供方法。
class Resource{
private String name;
private String sex;
private boolean flag=false;
public synchronized void set(String name,String sex){
if(flag)
try{
this.wait();
}catch(InterruptedException e){
}
this.name=name;
this.sex=sex;
flag=true;
this.notify();
}
public synchronized void Out(){
if(!flag)
try{
this.wait();
}catch(InterruptedException e){
}
System.out.println(name+"...优化..."+sex);
flag=true;
this.notify();
}
}
//输入
class Input implements Runnable{
Resource r;
Input(Resource r){
this.r=r;
}
public void run(){
int x=0;
while(true){
if(x==0){
r.set("mike","nan");
}else{
r.set("mike","nan");
}
x=(x+1)%2;
}
}
}
//输出
class Output implements Runnable{
Resource r;
Output(Resource r){
this.r=r;
}
public void run(){
while(true){
r.Out();
}
}
}
public class NofityDemo {
public static void main(String[] args) {
//创建资源
Resource r=new Resource();
//创建任务
Input in=new Input(r);
Output out=new Output(r);
//创建线程,执行路径
Thread t1=new Thread(in);
Thread t2=new Thread(out);
//开启线程
t1.start();
t2.start();
}
}
运行:思考2:wait(),sleep()有什么区别?
wait()释放执行权,释放锁;sleep()释放cpu执行权,不释放锁。