说到线程就必须先要了解一下进程的概念,进程其实就是一个应用程序。然而一个应用程序中会有很多的线程组成这是因为一个应用程序中的许多部分是会出现并发的(即同时发生)所以我们就需要把同时发生的那些部分用线程来进行封装,这样可以让它们去争夺CPU的执行权,因为CPU的执行速度很快所以让那些被封装成线程的代码就会看起来是在同时发生!然而有一种情况下我们需要注意线程的安全问题:那就是在有很多个线程在执行相同的代码的情况下,需要进行同步处理只有这样才能够避免因为一个线程在执行代码到一半的时候被另外某个线程抢到执行权而导致数据的错乱。

package com.isthreadDemo;
 /* 生产者与消费者的问题:
  * 生产一个消费一个
  * 两个或两个以上的线程处理不同的代码,并且要通过同步与等待唤醒机制
  * 来处理问题
  * 
  * */
 public class ThreadDemo2 {
public static void main(String[] args){
Product p = new Product();//创建一个Product对象
Production pt = new Production(p);
Sale s = new Sale(p);
Thread t1 = new Thread(pt);
Thread t2 = new Thread(pt);
Thread t3 = new Thread(s);
Thread t4 = new Thread(s);
t1.start();
t2.start();
t3.start();
t4.start();
}
 }
 //创建一个产品类
 class Product{
private String name;//产品名称
private int conter = 1;//产品价格
boolean flag = false;
public synchronized void set(String name){//创建一个set()方法用于设置产品信息
//t1(获取执行权) t2(等待) 
while(flag){
try{
wait();//当t1执行到这里就会等待在这里,当t2执行到这里也等在这里
}
catch(InterruptedException e){
System.out.println(e);
}
}
this.name = name+"..."+(conter++);
System.out.println(Thread.currentThread().getName()+"...生产了..."+this.name);
flag = true;
notifyAll();
}
public synchronized void out(){
while(!flag){
try{
wait();
/*在if语句中如果线程等在了这里,
接下来被唤醒后如果抢到了执行权的话不会再重复判断标记
这就是为什么某个商品被消费了两次
或更多(有不止一个线程执行这段代码)
这时候为了能够不出现这种没有判断标记就执行下面代码的情况
就需要让执行这个代码的其他线程重新判断标记。
所以选择while循环进行重复判断。
*/
}
catch(InterruptedException e){
System.out.println(e);
}
}
System.out.println(Thread.currentThread().getName()+"---消费了------"+name);
flag = false;
notifyAll();
}

 }
 //创建一个类专门用于生产产品
 class Production implements Runnable{
private Product p;
Production(Product p){
this.p = p;
}
public void run(){
for(int i = 0;i <= 300;i++){
p.set("商品");
}
}
 }
 class Sale implements Runnable{
private Product p;
Sale(Product p){
this.p = p;
}
public void run(){
for(int i = 0;i <= 300;i++){
p.out();
} 
}
 }