多线程之间如何实现通讯
什么是多线程之间通讯?
多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同。
画图如下:
我这里有个例子:就是弄两个线程,一个进行写,一个进行读,写的话,如果是偶数,就是java,男。如果是奇数,就是php 女,。
代码如下:
package com.newDemo.controller.test;
//共享资源
class res{
public String userSex;
public String userName;
}
//生产者线程
class inputThread extends Thread{
res res;
public inputThread(res res){
this.res = res;
}
public void run(){
int count=0;
while(true){
if(count==0){
res.userName="java";
res.userSex="男";
}else{
res.userName="php";
res.userSex="女";
}
count = (count + 1) % 2;
}
}
}
//消费者线程
class outThread extends Thread{
res res;
public outThread(res res){
this.res = res;
}
public void run(){
while(true){
System.out.println(res.userName + "--" + res.userSex);
}
}
}
public class threadDemo16 {
public static void main(String[] args) {
res res = new res();
inputThread intThrad = new inputThread(res);
outThread outThread = new outThread(res);
intThrad.start();
outThread.start();
}
}
结果如下:
发现结果乱了,出现了线程安全问题,我第一时间想到了synchronized同步代码块,两个线程用同一把锁,所以改进一下:
package com.newDemo.controller.test;
//共享资源
class res{
public String userSex;
public String userName;
}
//生产者线程
class inputThread extends Thread{
res res;
public inputThread(res res){
this.res = res;
}
public void run(){
int count=0;
while(true){
synchronized (res) {
if (count == 0) {
res.userName = "java";
res.userSex = "男";
} else {
res.userName = "php";
res.userSex = "女";
}
count = (count + 1) % 2;
}
}
}
}
//消费者线程
class outThread extends Thread{
res res;
public outThread(res res){
this.res = res;
}
public void run(){
while (true) {
synchronized (res) {
System.out.println(res.userName + "--" + res.userSex);
}
}
}
}
public class threadDemo16 {
public static void main(String[] args) {
res res = new res();
inputThread intThrad = new inputThread(res);
outThread outThread = new outThread(res);
intThrad.start();
outThread.start();
}
}
就是给两个线程都加了同步代码块,锁都是res。结果如下;
发现了问题:现在是数据同步保证一致了,安全保证了,但是有重复消费的情况
解决方案如下:
生产者线程生产一个,消费者线程里面消费
生产者线程么有生产,消费者线程不能进行读
消费者线程么有消费完,生产者线程不能生产
问题来了,那么咋样让两个线程一个等另一个呢,多线程里面有wait()和notify()
wait:让当前线程从运行状态变为休眠状态,并且会释放锁的资源给苏醒的线程
notify:让当前线程从休眠状态变为运行状态,唤醒线程
但是这两个使用也有条件:
必须在线程同步中才能使用,而且必须要是同一把锁的资源
所以代码如下:
package com.newDemo.controller.test;
//共享资源
class res{
public String userSex;
public String userName;
//线程通讯标识 (false 生产者线程写,消费者线程等待)(true 消费者线程读,生产者线程等待)
public boolean flag = false;
}
//生产者线程
class inputThread extends Thread{
res res;
public inputThread(res res){
this.res = res;
}
public void run(){
int count=0;
while(true){
synchronized (res) {
if(res.flag){
try {
res.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (count == 0) {
res.userName = "java";
res.userSex = "男";
} else {
res.userName = "php";
res.userSex = "女";
}
count = (count + 1) % 2;
res.flag=true;
res.notify();
}
}
}
}
//消费者线程
class outThread extends Thread{
res res;
public outThread(res res){
this.res = res;
}
public void run(){
while (true) {
synchronized (res) {
if(!res.flag){
try {
res.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(res.userName + "--" + res.userSex);
res.flag=false;
res.notify();
}
}
}
}
public class threadDemo16 {
public static void main(String[] args) {
res res = new res();
inputThread intThrad = new inputThread(res);
outThread outThread = new outThread(res);
intThrad.start();
outThread.start();
}
}
结果如下:
这样就可以解决了多线程之间通讯的问题