多线程模式

single thread execution

single thread execution主要思想是:在同一时刻,对于某一共享资源,只能有一个人访问,即资源同步。

package gate;

public class Person {
    private String name;
    private String address;
    
    public synchronized void  setNameAddress(String name,String address){
        this.name = name;
        this.address = address;
        check();
    }
    private  void check(){
        if(!name.equals(address)){
            System.out.println("problem:"+name+","+address);
        }
        
    }
}

/*****************************/

package gate;

public class RunThread extends Thread {
    private Person person;
    private String name;
    private String address;
    public RunThread(Person person,String name,String address){
        this.person =person;
        this.name  =name;
        this.address  =address;
    }
    
    public  void run(){
        while(true){
            person.setNameAddress(name,address);
            
        }
    }

}
/*******************************/
package gate;

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        new RunThread(person,"345","345").start();
    
        new RunThread(person,"456","456").start();
    
    }
}

参与者如下:
共享资源(Person ),资源利用者(RunThread) 
对于共享资源中的线程非安全方法需要加入锁机制(
synchronized或者ReentrantLock)进行同步,确保在某个时间点只有一个线程在访问该方法。
适应的时机:
多线程环境(废话),资源共享(又是废话),资源的状态发生变化(状态不会变化的对象线程安全的)

 

guarded suspension pattern和productor-consumer pattern

 请求发出以后,如果没有准备好的一直等待到数据准备好在返回---》谨慎的等待(恶心的名字)

package guarded;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class Data {
    
    private BlockingQueue<String>  blockingQueue = new ArrayBlockingQueue<String>(1);
    
    public void putRequest(String content){
        try {
            blockingQueue.put(content);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    public String getRequest(){
        try {
            return blockingQueue.take();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "";
    }
}
/*******************************************/


package guarded;

import java.util.Random;

public class ClientThread extends Thread{
    private Data data;
    
    public ClientThread(Data data){
        this.data =data;
    }
    public void run(){
        for (int i = 0; i < 1000; i++) {
            System.out.println("put content:"+i);
            data.putRequest(String.valueOf(i));
            try {
                Thread.sleep(new Random().nextInt(1000));
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
/***********************************/

package guarded;

import java.util.Random;

public class ServerThread extends Thread {
    private Data data;
    
    public ServerThread(Data data){
        this.data =data;
    }
    
    public void run(){
        while(true){
            System.out.println("get content:"+data.getRequest());
            try {
                Thread.sleep(new Random().nextInt(1000));
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
/**********************************/
package guarded;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Data data = new Data();
        new ServerThread(data).start();
        new ClientThread(data).start();
    }

}

guarded suspension pattern和productor-comsumer(生产者消费者)很像,这里Data的blockingQueue的容量是1,productor-comsumer则大于一,productor-comsumer也基本上是多对多关系。
jdk1.4以前主要用wait(),notifyAll()进行控制,现在用BlockingQueue更加简单

参与者:
Data(存放资源和等待条件等一系列条件和业务处理的类)  ServerThread和ClientThread(处理结果和请求发起的线程)

 

Read—Write Lock Pattern

Read—Write Lock Pattern将读写分离,在读取之前,获得用来读取的锁,在写在之前,获得用来写入的锁,
读写的锁的关系是:有人读取(多个也无所谓)时,写不能进行;有人写入时,其他的写和读不能进行。

package readwritelock;


public class Data {
    
    private final char[] buffer;
    private final ReadWriteLock readWriteLock = new ReadWriteLock();
    
    public Data(int size){
        this.buffer=new char[size];
        for (int i = 0; i < buffer.length; i++) {
            buffer[i] ='*';
        }
    }
    
    public char[]  read(){
        readWriteLock.readLock();
        try{
            return doRead();
        }finally{
            readWriteLock.readUnLock();
        }
    }
    
    public void write(char c){
        readWriteLock.writeLock();
        try{
            doWrite(c);
        }finally{
            readWriteLock.writeUnLock();
        }
    }
    
    private char[] doRead(){
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return buffer;
    }
    
    private void doWrite(char c){
        for (int i = 0; i < buffer.length; i++) {
            buffer[i] =c;
        }
    }
    

}
/*******************************************/
package readwritelock;


public class ReadThread extends Thread {
    private Data data;

    public ReadThread(Data data) {
        this.data = data;
    }

    public void run() {
        while (true) {
            char[] c = data.read();
            System.out.println(Thread.currentThread().getName() + ": "
                    + String.valueOf(c));
        }
    }
}
/*******************************************/
package readwritelock;


public class ReadWriteLock {
    private volatile int readLocks = 0;
    private volatile int writeLocks = 0;
    private volatile int waitLocks = 0;
    
    private volatile boolean writeFirst =true;

    public synchronized void readLock() {
        // 写锁或者等待锁大于0,读阻塞
        while (writeLocks > 0 || writeFirst&&waitLocks > 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        readLocks++;
    }

    public synchronized void readUnLock() {
        readLocks--;
        writeFirst =true;
        notifyAll();
    }

    public synchronized void writeLock() {
        // 写等待
        waitLocks++;
        try {
            while (readLocks > 0||writeLocks>0) {
                wait();
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            waitLocks --;
        }
        writeLocks++;
    }
    public synchronized void writeUnLock() {
        writeLocks--;
        writeFirst =false;
        notifyAll();
    }
}
/*********************************************/
package readwritelock;

import java.util.Random;

public class WriterThread extends Thread {
    
    private Data data;
    private String str;
    private int index =0;
    public WriterThread(Data data, String str) {
        this.data = data;
        this.str = str;
    }
    public void run(){
        while(true){
            data.write(get());
            try {
                Thread.sleep(new Random().nextInt(200));
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    private char get(){
        char a =str.charAt(index);
        index++;
        if(index>=str.length()){
            index = 0;
        }
        return a;
    }
}
/*********************************************/
package readwritelock;

public class Test {
public static void main(String[] args) {
    Data data = new Data(10);
    new WriterThread(data, "asdsad");
    new WriterThread(data, "有亲戚吗");
    new ReadThread(data).start();

    
}
}

jdk concurrent 包里面有CurrentHashMap和CopyOnWriteArrayList都有锁的概念
CurrentHashMap有个分离锁,把Map分成几个段,对于一个段的写入,不影响其他段的读写,
CopyOnWriteArrayList可以并发的读取,并且返回一个稳定的迭代器,对于写入,是重新开辟一个数组,拷贝原来的数据进行修改,修改完成后再合并回去.  
jdk concurrent的 ReentrantReadWriteLock就是一个可以重入的读写锁

 

posted @ 2012-07-16 13:40  nod0620  阅读(814)  评论(0编辑  收藏  举报