/*
输入一个姓名和性别,然后用另一个线程输出
*/
class Resource{
String name;
String sex;
boolean flag = false; //用来作为判定输入是否输出的标识
}
class Input implements Runnable{
private Resource res;
Input(Resource res){
this.res = res;
}
public void run(){
int x = 0;
while(true){
//两个线程用同一个对象锁
synchronized(res){
if (res.flag)
try{
res.wait();
}catch(InterruptedException e){
}
if(x==0){
res.name = "张三";
res.sex = "男";
}else {
res.name = "WWW";
res.sex = "woman";
}
x = (x+1)%2;
res.flag = true;
res.notify();
}
}
}
}
class Output implements Runnable{
private Resource res;
Output(Resource res){
this.res = res;
}
public void run(){
while(true){
//两个线程用同一个对象锁
synchronized(res){
if(!res.flag)
try{
res.wait();
}catch(InterruptedException e){
}
System.out.println(res.name+"......"+res.sex);
res.flag = false;
res.notify();
}
}
}
}
class ThreadCommunicationDemo{
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();
}
}
下面的是优化版本
/**
用一个线程输入姓名和性别,用另一个线程输出姓名和性别的
优化版本!
@author zck;
@version V1.1;
*/
class Resource{
private String name;
private String sex;
private boolean flag = false; //用来作为判定输入是否已经输出的标识
public synchronized void setNameSex(String name,String sex){
if (flag){
try{
this.wait();
}catch(InterruptedException e){
}
}
this.name = name;
this.sex = sex;
flag = true;
notify();
}
public synchronized void getNameSex(){
if (!flag){
try{
this.wait();
}catch(InterruptedException e){
}
}
System.out.println(this.name+"......"+this.sex);
flag = false;
notify();
}
}
class Input implements Runnable{
private Resource res;
Input(Resource res){
this.res = res;
}
public void run(){
int x = 0;
while(true){
if(x==0){
res.setNameSex("张三","男");
}else {
res.setNameSex("WWW","woman");
}
x = (x+1)%2;
}
}
}
class Output implements Runnable{
private Resource res;
Output(Resource res){
this.res = res;
}
public void run(){
while(true){
res.getNameSex();
}
}
}
class ThreadCommunicationDemo2{ //优化版本
public static void main(String[] args){
Resource r = new Resource();
new Thread(new Input(r)).start();
new Thread(new Output(r)).start();
}
}
在屏幕上打印输出时,有时候会出现生产两次却只消费了一次的情况,这与预期的生产一次消费一次不符合,这种安全隐患来自于flag的if判断,因为只判定一次,当生产线程1通过if判断时,执行完wait语句就失去了执行权,然后接下来消费线程1执行,然后生产线程2执行(因为此时flag是false),当生产线程2执行完时,flag变成了true,但是由于生产线程1已经在之前中通过了if判断,当生产线程1获得执行权时,就会再生产一次;
打印结果:
生产商品1
消费商品1
生产商品2
生产商品3
消费商品3
改进方法就是将if换成while判断
还有一种安全隐患就是notify叫醒的线程池里本类线程,就会出现叫醒生产线程1叫醒生产线程2,然后所有线程都挂了(都进入wait状态);处理方式就是改notify为notifyAll,干脆全叫醒,就不会出现所有线程一起挂在那儿的情况了;
class ProducerConsumerDemo{
public static void main(String[] args){
ProducerConsumer pc = new ProducerConsumer();
Producer pro = new Producer(pc);
Consumer con = new Consumer(pc);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class ProducerConsumer{
private String name;
private int count = 1;
private boolean flag = false;
public synchronized void setName(String name){
while(true){
while(flag){
try{
wait();
}catch(InterruptedException e){
}
}
this.name = name+"..."+count++;
System.out.println(Thread.currentThread().getName()+"---生产---"+this.name);
flag = true;
this.notifyAll();
}
}
public synchronized void getName(){
while(true){
while(!flag){
try{
wait();
}catch(InterruptedException e){
}
}
System.out.println(Thread.currentThread().getName()+"---消费-----"+this.name);
flag = false;
this.notifyAll();
}
}
}
class Producer implements Runnable{
ProducerConsumer pc;
Producer(ProducerConsumer pc){
this.pc = pc;
}
public void run(){
pc.setName("商品");
}
}
class Consumer implements Runnable{
ProducerConsumer pc;
Consumer(ProducerConsumer pc){
this.pc = pc;
}
public void run(){
pc.getName();
}
}
下面是java5.0改进版本
1. 引入了lock代替synchronized,condition对象的await代替wait,signal和signalAll代替notify和notifyAll;
import java.util.concurrent.locks.*;
class ProducerConsumerDemo2{
public static void main(String[] args){
ProducerConsumer pc = new ProducerConsumer();
Producer pro = new Producer(pc);
Consumer con = new Consumer(pc);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class ProducerConsumer{
private String name;
private int count = 1;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition_pro = lock.newCondition();
private Condition condition_con = lock.newCondition();
public void setName(String name) throws InterruptedException{
lock.lock();
try{
while(flag){
condition_pro.await();
}
this.name = name+"..."+count++;
System.out.println(Thread.currentThread().getName()+"---生产---"+this.name);
flag = true;
condition_con.signalAll();
}finally{
lock.unlock();
}
}
public void getName() throws InterruptedException{
lock.lock();
try{
while(!flag){
condition_con.await();
}
System.out.println(Thread.currentThread().getName()+"---消费-----"+this.name);
flag = false;
condition_pro.signalAll();
}finally{
lock.unlock();
}
}
}
class Producer implements Runnable{
ProducerConsumer pc;
Producer(ProducerConsumer pc){
this.pc = pc;
}
public void run(){
while(true){
try{
pc.setName("商品");
}catch(InterruptedException e){
}
}
}
}
class Consumer implements Runnable{
ProducerConsumer pc;
Consumer(ProducerConsumer pc){
this.pc = pc;
}
public void run(){
while(true){
try{
pc.getName();
}catch(InterruptedException e){
}
}
}
}
class InterruptThreadDemo{
public static void main(String[] args){
int num = 0;
TestThread tt = new TestThread();
Thread t1 = new Thread(tt);
Thread t2 = new Thread(tt);
t1.start();
t2.start();
while(true){
if(num++ == 60){
//tt.changeFlag();
//强制唤醒了t1和t2线程
t1.interrupt();
t2.interrupt();
break;
}
System.out.println(Thread.currentThread().getName()+"..."+num);
}
}
}
class TestThread implements Runnable{
private boolean flag = true;
public synchronized void run(){
while(flag){
try{
wait();
}catch(InterruptedException e){
System.out.println(Thread.currentThread().getName()+"InterruptedException");
//结束循环实则为结束进程
flag = false;
}
System.out.println(Thread.currentThread().getName()+"run.....");
}
}
public void changeFlag(){
flag = false;
}
}
class InterruptThreadDemo{
public static void main(String[] args){
int num = 0;
TestThread tt = new TestThread();
Thread t1 = new Thread(tt);
Thread t2 = new Thread(tt);
t1.setDaemon(true);
t2.setDaemon(true);
t1.start();
t2.start();
while(true){
if(num++ == 60){
//tt.changeFlag();
//强制唤醒了t1和t2线程
//t1.interrupt();
//t2.interrupt();
break;
}
System.out.println(Thread.currentThread().getName()+"..."+num);
}
}
}
class TestThread implements Runnable{
private boolean flag = true;
public void run(){
while(flag){
System.out.println(Thread.currentThread().getName()+"run.....");
}
}
public void changeFlag(){
flag = false;
}
}
class JoinDemo{
public static void main(String[] args) throws InterruptedException{
Join jo = new Join();
Thread t1 = new Thread(jo);
Thread t2 = new Thread(jo);
t1.start();
t1.setPriority(Thread.MAX_PRIORITY);
t2.start();
//t1.join();
for(int x = 0;x<80;x++){
System.out.println(Thread.currentThread().toString()+"....."+x);
}
}
}
class Join implements Runnable{
public void run(){
for (int x = 0;x<70;x++){
System.out.println(Thread.currentThread().toString()+"..."+x);
//Thread.yield();
}
}
}