一、线程间通信
如果每个线程间都孤立的运行,那就会造资源浪费。所以在现实中,我们需要这些线程间可以按照指定的规则共同完成一件任务,所以这些线程之间就需要互相协调,这个过程被称为线程的通信。
线程通信就是当多个线程共同操作共享的资源时,互相告知自己的状态以避免资源争夺。
线程间通讯的方式: (存在多种方式,这里只写了共享内存,等待唤醒)
1.共享内存:
使用这种方式进行线程通信,通常会设置一个共享变量。然后多个线程去操作同一个共享变量。从而达到线程通讯的目的。同时在多个线程操作同一个资源的过程中,必须要考虑的是共享变量的同步问题,这也共享内存容易出错的原因所在。
在这种通讯模型中,不同的线程之间是没有直接联系的。都是通过共享变量这个“中间人”来进行交互。而这个“中间人”必要情况下还需被保护在临界区内(加锁或同步)。由此可见,一旦共享变量变得多起来,并且涉及到多种不同线程对象的交互,这种管理会变得非常复杂,极容易出现死锁等问题。
例如:设置一个共享资源Resoure类,Input类用来输入信息,Output用来提取信息,ResourceDemo类用来调用执行,
public class Resource { String name; String sex; } public class Input implements Runnable{ Resource r; Input(Resource r){ this.r = r; } public void run(){ int x = 0; while(true) synchronized (r) { //Input与Output共用一个锁r if (x == 0) { r.name = "小明"; r.sex = "男"; } else { r.name = "小红"; r.sex = "女"; } } x = (x + 1) % 2; } } } public class Output implements Runnable{ Resource r; Output(Resource r){ this.r = r; } public void run(){ while(true) { synchronized (r) { System.out.println(r.name + "...." + r.sex); } } } } public class ResourceDemo { public static void main(String[] args) { Resource r = new Resource(); Input in = new Input(r); //将对象r作为参数传递,Input,Output共用一个锁 Output out = new Output(r); Thread t1 = new Thread(in); Thread t2 = new Thread(out); t1.start(); t2.start(); } }
2.等待唤醒机制:
涉及的方法:
<1>wait(); 让线程处于冻结状态,被wait的线程会被存储到线程池中。
<2>notify(); 唤醒线程池中的一个线程(任意)
<3>notifyAll(); 唤醒线程池中的所有线程。
这些方法都必须定义在同步中,因为这些方法是用于操作线程的方法。
必须要明确到底操作的是那个锁上的线程。
例如:
public class Resource { private String name; private String sex; private boolean flag = false; public synchronized void set(String name,String sex){ if(flag) //flag为真时,信息以及输入,需要被读取,所以输入进程等待 try{this.wait();}catch(InterruptedException e){} this.name = name; this.sex = sex; flag = true; this.notify(); //输出进程被唤醒 } public synchronized void out(){ if(!flag) //flag为假时,信息已经输出,需要再次输入,输出进程等待 try{this.wait();}catch(InterruptedException e){} System.out.println(name+"...."+sex); flag = false; this.notify(); //输入进程被唤醒 } } public 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("小明","男"); } else { r.set("小红","女"); } x = (x + 1) % 2; } } } public class Output implements Runnable{ Resource r; Output(Resource r){ this.r = r; } public void run(){ while(true) { r.out(); } } } public class ResourceDemo { 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(); } }
原文:https://www.cnblogs.com/gmangofight/p/14606777.html