歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java多線程(同步與死鎖問題,生產者與消費者問題)

Java多線程(同步與死鎖問題,生產者與消費者問題)

日期:2017/3/1 9:30:37   编辑:Linux編程

首先我們來看同步與死鎖問題:

所謂死鎖,就是A擁有banana,B擁有apple。

A對B說:你把apple給我,我就把banana給你。

B對A說:你把banana給我,我就把apple給你。

但是A和B都在等待對方的答復,那麼這樣最終的結果就是A得不到apple,B也得不到banana。這種死循環就是死鎖。

於是我們可以模擬上面的描述,寫出以下代碼:

類A代表A這個人,

public class A {
public void say(){
System.out.println("A said to B: if you give me the apple, I will give you the banana.");
}
public void get(){
System.out.println("A get the apple.");
}
}

類B代表B這個人,

public class B {
public void say(){
System.out.println("B said to A: if you give me the banana, I will give you the apple.");
}
public void get(){
System.out.println("B get the banana.");
}
}

類ThreadDeadLock代表死鎖類,

public class ThreadDeadLock implements Runnable{
private static A a=new A();
private static B b=new B();
public boolean flag=false;
public void run(){
if(flag){
synchronized(a){
a.say();
try{
Thread.sleep(500);
}catch(InterruptedException e){
e.printStackTrace();
}
synchronized(b){
a.get();
}
}
}else{
synchronized(b){
b.say();
try{
Thread.sleep(500);
}catch(InterruptedException e){
e.printStackTrace();
}
synchronized(a){
b.get();
}
}
}
}
}

下面是主類:

public class Main{
public static void main(String[] args){
ThreadDeadLock t1=new ThreadDeadLock();
ThreadDeadLock t2=new ThreadDeadLock();
t1.flag=true;
t2.flag=false;
Thread thA=new Thread(t1);
Thread thB=new Thread(t2);
thA.start();
thB.start();
}
}

程序運行結果:
A said to B: if you give me the apple, I will give you the banana.
B said to A: if you give me the banana, I will give you the apple.

從以上的程序運行,我們可以發現,兩個線程都在等待對方的執行完成,這樣,程序也就無法繼續執行,從而造成了死鎖運行現象。

下面我們來看生產者與消費者問題:

所謂生產者與消費者問題,很簡單,過程就是生產者不斷生產產品,消費者不斷取走產品。

Producer生產product,Consumer消費product。

於是,我們先定義product類:

public class Product {
private String name="product";
private boolean flag=false;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public synchronized void set(String name){
if(!flag){
try{
super.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
this.setName(name);
try{
Thread.sleep(300);
}catch(InterruptedException e){
e.printStackTrace();
}
flag=false;
super.notify();
}
public synchronized void get(){
if(flag){
try{
super.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
try{
Thread.sleep(300);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(this.getName());
flag=true;
super.notify();
}
}

這裡加入了等待與喚醒,並增加一個標志位flag,flag為true時,表示可以生產,但不能取走,此時如果線程執行到了消費者線程,則應該等待,如果flag為false,則表示可以取走,但是不能生產,如果生產者線程運行,則應該等待。

Producer類:

public class Producer implements Runnable{
private Product product=null;
public Producer(Product product){
this.product=product;
}
public void run(){
for(int i=0;i<50;++i){
this.product.set("product");
}
}
}

Consumer類:

public class Consumer implements Runnable{
private Product product=null;
public Consumer(Product product){
this.product=product;
}
public void run(){
for(int i=0;i<50;++i){
try{
Thread.sleep(100);
}catch(InterruptedException e){
e.printStackTrace();
}
this.product.get();
}
}
}

然後是主類:

public class Main{
public static void main(String[] args){
Product product=new Product();
Producer pro=new Producer(product);
Consumer con=new Consumer(product);
new Thread(pro).start();
new Thread(con).start();
}
}

於是我們知道,生產者每生產一個產品,消費者就取走一個產品,消費者每取走一個產品,就要等待生產者生產。

Copyright © Linux教程網 All Rights Reserved