`

j2se------多线程--队与信号量

    博客分类:
  • J2SE
阅读更多
下面介绍的是对wait()和notify()以及synchronized()的封装


等待队列的等待和唤醒机制与常用的信号量机制有些相似之处。没错,实际上信号量机制是等待队列机制是同步机制在更高层次上的封装和改良,因为信号量的操作在底层实际上就是通过等待队列的同步机制实现。只不过在在使用信号量时,我们通常强调是资源共享,因而把信号量预先设置为或者,表示资源可用与否。而使用等待队列则意味着,我们在执行某个操作时,强调某个条件满足与否,从而决定当前进程的休眠


1。BlockingQueue

阻塞队列提供了可以阻塞的put和take方法,以及与之等价的可以指定超时的offer和 poll。如果Queue是空的,那么take方法会一直阻塞,直到有元素可用。如果Queue是有线长度的,队列满的时候put方法也会阻塞。 BlockingQueue可以很好的支持生产者和消费者模式,生产者往队列里put,消费者从队列里get,两者能够得好很好的同步。 BlockingQueue的实现类LinkedBlockingQueue和ArrayBlockingQueue是FIFO队列,PriorityBlockingQueue是一个按优先级排序的队列。使用BlockingQueue构建的一个生产者与消费例子:

消费者:
public class Consumer implements Runnable {

	private BlockingQueue<Food> queue;
	private ExecutorService exec;

	public Consumer(BlockingQueue<Food> queue, ExecutorService exec) {
		this.queue = queue;
		this.exec = exec;
	}

	@Override
	public void run() {
		while (!exec.isShutdown()) {
			try {
				Thread.sleep(2000);
				Food food = queue.take();
				System.out.println("Consumer " + food);
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (RejectedExecutionException e) {

			}
		}
	}
}
生产者:
public class Producer implements Runnable {

	private BlockingQueue<Food> queue;
	private ExecutorService exec;

	public Producer(BlockingQueue<Food> queue, ExecutorService exec) {
		this.queue = queue;
		this.exec = exec;
	}

	@Override
	public void run() {
		while (!exec.isShutdown()) {
			Food food = new Food();
			try {
				Thread.sleep(4000);
				queue.put(food);
				System.out.println("Produce " + food);
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (RejectedExecutionException e) {

			}
		}
	}
}
Main:
BlockingQueue<Food> queue = new ArrayBlockingQueue<Food>(5);
ExecutorService exec = Executors.newFixedThreadPool(3);
Producer p1 = new Producer(queue, exec);
Producer p2 = new Producer(queue, exec);

Consumer c1 = new Consumer(queue, exec);
	
exec.execute(p1);
exec.execute(p2);
exec.execute(c1);
try {
	Thread.sleep(10000);
} catch (InterruptedException ignored) {
}
exec.shutdown();

2。Semaphore,信号量
使用信号量进行同步和互斥的控制是最经典的并发模型,java中也提高支持。一个Semaphore管理一个有效的许可 集,许可基的数量通过构造函数传入,通过acquire方法申请一个许可,许可数为0则阻塞线程,否则许可数减一,使用release方法释放一个许个,许可数加一。一个技术量为1的Semaphore为二元信号量,相当于一个互斥锁,表示不可重入的锁。一个使用信号量控制并发容器上届的例子:
public class BoundedHashSet<T> {
	private final Set<T> set;
	private final Semaphore sem;

	public BoundedHashSet(int bound) {
		set = Collections.synchronizedSet(new HashSet<T>());
		sem = new Semaphore(bound);
	}

	public boolean add(T o) throws InterruptedException {
		sem.acquire();
		boolean wasAdded = false;
		try {
			wasAdded = set.add(o);
			return wasAdded;
		} finally {
			if (!wasAdded)
				sem.release();
		}
	}

	public boolean remove(Object o) {
		boolean wasRemoved = set.remove(o);
		if (wasRemoved)
			sem.release();
		return wasRemoved;
	}
}




分享到:
评论

相关推荐

    Android面试复习资料

    - 并发与同步:熟悉互斥锁、信号量、条件变量等同步原语。 - 手机操作系统特性:Android的Dalvik和ART运行时,内存管理策略。 在面试中,这些知识点的深度和广度都会被考察。除了理论知识,面试官还可能要求你...

    java经典面试题

    - 信号量:管理多个进程对共享资源的访问。 - 共享内存:允许多个进程共享同一段内存区域。 - 套接字:允许不同进程间的网络通信。 6. **什么是虚拟内存**: - 虚拟内存是一种技术,它让程序可以使用比实际物理...

    The java.util.concurrent Synchronizer Framework

    - **信号量(Semaphore)**:控制同时访问某个资源或服务的数量。 - **屏障(CyclicBarrier)**:多个线程等待到达某个公共屏障点。 - **完成阶段(CompletionStage)**:表示计算任务的完成阶段,支持链式任务。 - ...

    马士兵TankWar

    《马士兵TankWar》是一款基于Java 2 Standard Edition (J2SE) 平台开发的简单游戏项目,旨在帮助学习者巩固和实践面向对象编程、多线程处理以及图形用户界面(GUI)设计等核心Java基础知识。在这个项目中,开发者...

    复习 J2SE基本内容 IO NIO AIO 的区别

    3. **线程模型**:BIO通常每个连接一个线程,NIO使用单线程或多线程(一个请求一个线程),AIO在数据准备好后才启动线程处理有效请求。 4. **选择器/通知机制**:NIO有选择器用于监控通道,AIO通过底层API实现异步...

    Java 并发核心编程

    Java提供了多种线程协作方式,如条件变量(Condition Variables)、信号量(Semaphores)、栅栏(Barriers)等,它们能够帮助开发者构建复杂且高效的多线程应用。 #### 六、总结 Java并发编程涉及多个层次的概念和...

    The java.util.concurrent synchronizer framework.pdf

    文档明确指出,Doug Lea为J2SE 5.0引入的java.util.concurrent包提供了一套精巧的同步器框架,这套框架极大地简化了并发控制的实现,并且在多个领域提供了高效的同步原语,如锁、条件变量、信号量、事件标志等。...

Global site tag (gtag.js) - Google Analytics