线程协作/线程通信
管程法
- 通过一个缓冲区,将部分数据存放在缓冲区中,在由缓冲区中的数据进行判断,对某偶一个线程进行等待或者唤醒。
- 通过
this.wait()
,让当前线程等待,并且释放当前线程对象对资源的锁,使得其他的线程可以使用到该资源 - 通过
this.notifyAll();
对等待的线程进行唤醒,wait()方法使当前线程进入等待状态,同时释放当前对象的锁。当另一个线程调用了相同对象上的notify()(或notifyAll())方法时,处于等待状态的线程将被唤醒并继续执行,重新尝试获取对象的锁。
使用生产者消费者的问题对管程法进行进一步的解释
- 创建生产者和消费者相关线程,同时使用使用一个商品资源,创建一个商店缓冲区,对商品资源进行一个临时的存储以及线程之间的交互。
- 将缓冲区大小设置为10 。可以存储10件商品,当购买者购买是商品时,如果商店缓冲区中商品存在,则卖与消费者同时商品数-1,若没有则,消费者释放对于商品的锁,将资源交由生产者生产,当生产者将商店缓冲区中的商品数目生产到10,或者商品数>0时,通知消费者购买商品,实现线程之间的交互。
package com.XianCheng.ImportPort;
public class TestPC {
public static void main(String[] args) {
buffer b = new buffer();
new producer(b).start();
new buyer(b).start();
}
}
class Chicken{
int id;
public Chicken(int id) {
this.id = id;
}
}
class producer extends Thread{
buffer con;
public producer(buffer con){
this.con=con;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("生产了第"+i+"只鸡!");
con.push(new Chicken(i));
}
}
}
class buyer extends Thread
{
buffer con;
public buyer(buffer con){
this.con=con;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("购买者购买的第————》"+con.pop().id+"只鸡");
}
}
}
class buffer {
Chicken[] chicken=new Chicken[10];
int num=0;
public synchronized void push(Chicken chickens) {
if (num==chicken.length){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else {
chicken[num]=chickens;
num++;
this.notifyAll();
}
}
public synchronized Chicken pop(){
if (num==0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("num="+num);
num--;
Chicken chicken = this.chicken[num];
this.notifyAll();
return chicken;
}
}
信号灯法
- 信号灯法,通过对标志位的改变实现线程之间的交互。
- 信号灯法不需要使用一个缓冲区对数据进行短暂的存储。即只能一个线程运行一次后就将资源交由另一个线程使用。
- 假设有A,B两个线程,设置一个标志位flag,当标志位flag=true时,运行线程A,线程B等待,反之运行线程B,线程A等待。
- 代码看看,一下明白:
package com.XianCheng.ImportPort;
public class TestPC2 {
public static void main(String[] args) {
TV tv = new TV();
player player = new player(tv);
watch watch = new watch(tv);
player.start();
watch.start();
}
}
class player extends Thread{
TV tv;
public player(TV tv){
this.tv=tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if (i%2==0){
tv.play("快乐大本营");
}
tv.play("广告");
}
}
}
class watch extends Thread{
TV tv;
public watch(TV tv){
this.tv=tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
tv.see();
}
}
}
class TV{
String voice;
Boolean flag=true;
public synchronized void play(String voice){
if (!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("演员表演了"+voice);
this.notifyAll();
this.voice=voice;
this.flag=!this.flag;
}
public synchronized void see(){
if (flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("观众观看了节目:"+voice);
this.notifyAll();
this.flag=!this.flag;
}
}