java多執行緒之-執行緒間的通訊
阿新 • • 發佈:2018-12-04
一個生產者與一個消費者
-
使用的方法:
wait():使執行緒停止並釋放鎖。
notify():叫醒執行緒。 -
例子
工具類
public class ValueObject {
public static String value="";
}
生產者
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package Thread; /** * * @author zjq */ public class Product { private String lock; public Product(String lock) { this.lock = lock; } public void setValue() { try { synchronized (lock) { if (!ValueObject.value.equals("")) { lock.wait(); } String value = System.currentTimeMillis() + "_" + System.nanoTime(); System.out.println("set的值是" + value); ValueObject.value = value; lock.notify(); } } catch (Exception e) { e.printStackTrace(); } } }
消費者
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package Thread; /** * * @author zjq */ public class C { private String lock; public C(String lock){ super(); this.lock=lock; } public void getValue(){ try { synchronized(lock){ if (ValueObject.value.equals("")) { lock.wait(); } System.out.println("get的值是"+ValueObject.value); ValueObject.value=""; lock.notify(); } } catch (Exception e) { e.printStackTrace(); } } }
執行緒類
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package Thread; /** * * @author zjq */ public class ThreadP extends Thread{ private Product p; public ThreadP(Product p){ super(); this.p = p; } @Override public void run(){ while (true) { p.setValue(); } } }
執行緒類
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Thread;
/**
*
* @author zjq
*/
public class ThreadCc extends Thread{
private C c;
public ThreadCc(C c){
super();
this.c = c;
}
@Override
public void run(){
while (true) {
c.getValue();
}
}
//在這裡執行
public static void main(String[] args) {
String lock=new String("");
Product p = new Product(lock);
C c = new C(lock);
ThreadP pThread = new ThreadP(p);
ThreadCc rThread = new ThreadCc(c);
pThread.start();
rThread.start();
}
}
結果
set的值是1543303341507_1059415405779753
get的值是1543303341507_1059415405779753
set的值是1543303341507_1059415406123851
get的值是1543303341507_1059415406123851
set的值是1543303341508_1059415406526419
get的值是1543303341508_1059415406526419
set的值是1543303341508_1059415406739753
get的值是1543303341508_1059415406739753
set的值是1543303341508_1059415406818765
get的值是1543303341508_1059415406818765
set的值是1543303341508_1059415406979950
get的值是1543303341508_1059415406979950
set的值是1543303341508_1059415407143111
get的值是1543303341508_1059415407143111
多個消費者多個生產者
-
使用的方法
wait():停止執行緒釋放鎖。
notifyall():叫醒所有的執行緒。 -
例子
工具類
public class ValueObject {
public static String value="";
}
生產者
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Thread;
/**
*
* @author zjq
*/
public class Product {
private String lock;
public Product(String lock) {
this.lock = lock;
}
public void setValue() {
try {
synchronized (lock) {
if (!ValueObject.value.equals("")) {
System.out.println("生產者 "+Thread.currentThread().getName()+"waiting 了 *");
lock.wait();
}
String value = System.currentTimeMillis() + "_" + System.nanoTime();
System.out.println("生產者 " + Thread.currentThread().getName()+"RUNNING 了");
ValueObject.value = value;
lock.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
消費者
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Thread;
/**
*
* @author zjq
*/
public class C {
private String lock;
public C(String lock){
super();
this.lock=lock;
}
public void getValue(){
try {
synchronized(lock){
while (ValueObject.value.equals("")) {
System.out.println("消費者 "+Thread.currentThread().getName()+"waiting 了 *");
lock.wait();
}
System.out.println("消費者 " + Thread.currentThread().getName()+"RUNNING 了");
ValueObject.value="";
lock.notifyAll();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
執行緒類
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Thread;
/**
*
* @author zjq
*/
public class ThreadP extends Thread{
private Product p;
public ThreadP(Product p){
super();
this.p = p;
}
@Override
public void run(){
while (true) {
p.setValue();
}
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Thread;
/**
*
* @author zjq
*/
public class ThreadCc extends Thread{
private C c;
public ThreadCc(C c){
super();
this.c = c;
}
@Override
public void run(){
while (true) {
c.getValue();
}
}
public static void main(String[] args) throws InterruptedException {
String lock=new String("");
Product p = new Product(lock);
C c = new C(lock);
ThreadP[] pThread = new ThreadP[2];
ThreadCc[] rThread = new ThreadCc[2];
for(int i=0;i<2;i++){
pThread[i]=new ThreadP(p);
pThread[i].setName("生產者"+(i+1));
rThread[i]=new ThreadCc(c);
rThread[i].setName("消費者"+(i+1));
pThread[i].start();
rThread[i].start();
}
Thread.sleep(5000);
Thread[] threadArray = new Thread[Thread.currentThread().getThreadGroup().activeCount()];
Thread.currentThread().getThreadGroup().enumerate(threadArray);
for(int i=0;i<threadArray.length;i++){
System.out.println(threadArray[i].getName()+" "+threadArray[i].getState());
}
}
}
執行結果
生產者 生產者1RUNNING 了
消費者 消費者2RUNNING 了
消費者 消費者2waiting 了 *
消費者 消費者1waiting 了 *
生產者 生產者2RUNNING 了
生產者 生產者2waiting 了 *
........
結果分析:如果不適用notifyall的話,生產者之間相互喚醒的話就容易造執行緒的假死狀態。