线程同步基础(二)

6.修改锁的公平性

ReentrantLock和ReentrantReadWriteLock类的构造器都含有一个布尔参数fair,它允许你控制这两个类的行为。默认fair值是false,他称为非公平模式。在非公平模式下,当有很多线程在等待锁时,锁将选择他们中的一个来访问临界区,这个选择是没有任何约束的。如果fair值是true,则称为公平模式,锁会选择等待时间最长的访问临界区。这两种模式只适用于lock()和unlock()方法。而Lock接口的tryLock()方法没有将线程置于休眠,fair属性并不影响这个方法。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class PrintQueue {
	private final Lock queueLock = new ReentrantLock(true);
	public void printJob(Object object) {
		queueLock.lock();
		try {
			long duration = (long)(Math.random()*10000);
			System.out.println(Thread.currentThread().getName()+":PrintQueue: Printing a Job during "+(duration/1000)+" seconds");
			Thread.sleep(duration);
		} catch (InterruptedException e) {
			// TODO: handle exception
		}finally {
			queueLock.unlock();
		}
		queueLock.lock();
		try {
			long duration = (long)(Math.random()*10000);
			System.out.println(Thread.currentThread().getName()+":PrintQueue: Printing a Job during "+(duration/1000)+" seconds");
			Thread.sleep(duration);
		} catch (InterruptedException e) {
			// TODO: handle exception
		}finally {
			queueLock.unlock();
		}
	}
}
public class Job implements Runnable{
	private PrintQueue printQueue;
	

	public Job(PrintQueue printQueue) {
		this.printQueue = printQueue;
	}


	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName()+": Going to print a document");
		printQueue.printJob(new Object());
		System.out.println(Thread.currentThread().getName()+": The document has been printed");
	}

}
public class Main {
	public static void main(String[] args) {
		PrintQueue printQueue = new PrintQueue();
		Thread[] threads = new Thread[10];
		for (int i = 0; i < 10; i++) {
			threads[i] = new Thread(new Job(printQueue),"Thread "+i);
		}
		
		for (int i = 0; i < 10; i++) {
			threads[i].start();
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

7.在锁中使用多条件

一个锁可能关联一个或者多个条件,这些条件通过Condition接口声明。目的是允许线程获取锁并且查看等待的某一个条件是否满足,如果不满足就挂起直到某个线程唤醒他们。Condition接口提供了挂起线程和唤起线程的机制。
public class FileMock {
	private String[] content;
	private int index;
	public FileMock(int size, int length) {
		content = new String[size];
		StringBuffer buffer = new StringBuffer(length);
		for (int i = 0; i < content.length; i++) {
			for (int j = 0; j < length; j++) {
				int indice = (int)Math.random()*255;
				buffer.append((char)indice);
			}	
			content[i] = buffer.toString();
		}
		index = 0;
	}
	public boolean hasMoreLines() {
		return index<content.length;
	}
	public String  getLine() {
		if (this.hasMoreLines()) {
			System.out.println("Mock: "+(content.length-index));
			return content[index+1];
		}
		return null;
	}
}
import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Buffer {
	private LinkedList<String> buffer;
	private int maxSize;
	private ReentrantLock lock;
	private Condition lines;
	private Condition space;
	private boolean pendingLines;
	public Buffer(int maxSize) {
		this.maxSize = maxSize;
		buffer = new LinkedList<>();
		lock = new ReentrantLock();
		lines = lock.newCondition();
		space = lock.newCondition();
		pendingLines = true;
	}

	public void insert(String line) {
		lock.lock();
		try {
			while(buffer.size()==maxSize) {
				space.await();
			}
			buffer.offer(line);
			System.out.println(Thread.currentThread().getName()+": Inserted Line: "+buffer.size());
			lines.signalAll();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}
	public String  get() {
		String line = null;
		lock.lock();
		try {
			while((buffer.size()==0)&&(hasPendingLines())) {
				lines.await();
			}
			if (hasPendingLines()) {
				line = buffer.poll();
				System.out.println(Thread.currentThread().getName()+": Line Readed: "+buffer.size());
				space.signalAll();
			}
		} catch (InterruptedException e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
		return line;
	}
	public void setPendingLines(boolean pendingLines) {
		this.pendingLines = pendingLines;
	}
	public boolean hasPendingLines() {
		return pendingLines || buffer.size()>0;
	}
}
public class Producer implements Runnable{

	private FileMock mock;
	private Buffer buffer;
	
	public Producer(FileMock mock, Buffer buffer) {
		this.mock = mock;
		this.buffer = buffer;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		buffer.setPendingLines(true);
		while(mock.hasMoreLines()) {
			String line = mock.getLine();
			buffer.insert(line);
		}
		buffer.setPendingLines(false);
	}

}
public class Consumer implements Runnable{

	private Buffer buffer;
	public Consumer(Buffer buffer) {
		this.buffer = buffer;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(buffer.hasPendingLines()) {
			String line = buffer.get();
			processLine(line);
		}
	}
	private void processLine(String line) {
		try {
			Random random = new Random();
			Thread.sleep(random.nextInt(100));
		} catch (InterruptedException e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

}
public class Main {
	public static void main(String[] args) {
		FileMock mock = new FileMock(100, 10);
		Buffer buffer = new Buffer(20);
		Producer producer = new Producer(mock, buffer);
		Thread thread1 = new Thread(producer,"Producer");
		Consumer[] consumers= new Consumer[3];
		Thread[] threads = new Thread[3];
		for (int i = 0; i < 3; i++) {
			consumers[i] = new Consumer(buffer);
			threads[i] = new Thread(consumers[i],"Consumer "+i);
		}
		
		thread1.start();
		for (int i = 0; i < 3; i++) {
			threads[i].start();
		}
	}
}
与锁绑定的所有条件对象都是通过Lock接口声明的newCondition()方法创建的。在使用条件的时候,必须获取这个条件绑定的锁,所以带条件的代码必须在调用Lock对象的lock()方法和unlock()方法之间。
当线程调用条件的await()方法时,他将自动释放这个条件绑定的锁,其他某个线程才可以获取这个锁并且执行相同的操作,或者执行这个锁保护的另一个临界区代码。
Condition接口还提供了await()方法的其他形式:
await(long time,TimeUnit unit),直到发生以下情况之一前,线程将一直处于休眠状态
  • 其他某个线程中断当前线程
  • 其他某个线程调用了将当前线程挂起的条件的signal()或signalAll()方法
  • 指定的等待时间已经过去
awaitUninterruptibly():它是不可中断的。这个线程将休眠直到其他某个线程调用了将他挂起的条件的signal()或signalAll()方法
awaitUntil(Date date):直到发生以下情况之一前,线程将一直处于休眠状态
  • 其他的某个线程中断当前线程
  • 其他某个线程调用了将他挂起的条件的signal()或signalAll()方法
  • 指定的最后期限到了
也可以将条件和读写锁一起使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值