关键字:Synchronized、wait/notify、ReentrantLock、生产-消费者模型
这篇博文仅仅对java多线程的部分知识做个小结,欢迎大家补充。
Synchronized
说到多线程,大家(对于初学者来说)可能就会想到Synchronized这个关键字。Synchronized可以用在方法级别上,用来同步一个方法的访问,也可以同步一个代码块。形式如下:
// 同步方法
public synchronized void method(){
// 方法体
}
// 同步代码快
synchronized(object){
// 代码块
}
Synchronized 需要注意的是:Synchronized作用于方法时,Synchronized首先会对方法所属的对象加锁,对象的其他被Synchronized修饰的方法都不可以被其他线程访问,非Synchronized修饰发方法可以被多个线程同时访问。
wait/notify
wait/notify必须在Synchronized的作用范围内使用,也就是说wait/notify必须在同步方法体内或同步代码快内才有效,其他地方就会报IllegalMonitorStateException。
基于Synchronized、wait/notify机理实现生产-消费者模型
public class Basket {
private List<String> basket = new ArrayList<String>(10);
private boolean running = false ;
public void run(){
this.running = true;
}
public void stop(){
this.running = false;
}
public boolean isRunning(){
return running;
}
public void add(String e) {
synchronized (basket) {
while (basket.size() == 10) {
try {
basket.wait(); // 访问的线程会等待在此处,当再次被唤醒,从此处继续执行
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
basket.add(e);
String currentThreadName = Thread.currentThread().getName();
System.out.println("线程["+currentThreadName+"] "+e + " 生产一个产品");
basket.notifyAll();
}
}
public void remove(String msg) {
synchronized (basket) {
String currentThreadName = Thread.currentThread().getName();
while (basket.size() == 0) {
try {
System.out.println("线程["+currentThreadName+"] "+msg + ": please wait a little");
basket.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String result = basket.get(0);
basket.remove(0);
System.out.println("线程["+currentThreadName+"] "+msg + " 消费:" + result);
basket.notifyAll();
}
}
public void getResult() {
System.out.println(basket.toString());
}
}
生产者
class UProducer implements Runnable {
private String name = "";
private Basket basket;
public UProducer(String name, Basket basket) {
this.name = name;
this.basket = basket;
}
@Override
public void run() {
int i = 0;
while(basket.isRunning()){
basket.add(name + i++);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public String getName() {
return name;
}
}
消费者
class Customer implements Runnable {
private String name = "";
private Basket basket;
public Customer(String name, Basket basket) {
super();
this.name = name;
this.basket = basket;
}
@Override
public void run() {
int i = 0;
while(basket.isRunning()){
basket.remove(name + i++);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public String getName() {
return name;
}
}
测试代码
public static void main(String[] args) {
Basket basket = new Basket();
basket.run();
UProducer mrZhang = new UProducer("张三", basket);
UProducer mrLi = new UProducer("李四", basket);
Customer missWang = new Customer("王五", basket);
Customer missZhao = new Customer("赵六", basket);
new Thread(missWang, missWang.getName()).start();
new Thread(missZhao, missZhao.getName()).start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(mrZhang, mrZhang.getName()).start();
new Thread(mrLi, mrLi.getName()).start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
basket.stop();
basket.getResult();
}
Synchronized关键字可以很方便的实现简单的多线程问题,jvm默认的为我们提供了对象的加锁、释放锁功能。Synchronized关键字同时存在一些问题。如一个线程得不到对象的锁会永远的等待。
ReentrantLock
ReentrantLock是对Synchronized的加强,提供了线程竞争锁的等待时间、多条件下的线程等待策略等等强大的功能。
具体的方法请参考API
以下是对生产-消费者模型的改写
class Basket {
private static final int CAPACITY = 10;
private List<Bread> container = new ArrayList<Bread>(CAPACITY);
private ReentrantLock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();
public void add(Bread bread) {
try {
lock.lockInterruptibly();
while (container.size() == CAPACITY) {
System.out.println("货源[" + Thread.currentThread().getName() + "]:no more ,i will call you if i need");
notFull.await();
}
container.add(bread);
System.out.println("货源[" + Thread.currentThread().getName() + "]:进货:" + bread);
notEmpty.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void remove() {
try {
lock.lockInterruptibly();
while (container.size() == 0) {
System.out.println("销售[" + Thread.currentThread().getName() + "]: please wait a little");
notEmpty.await();
}
Bread bread = container.get(0);
container.remove(0);
System.out.println("销售[" + Thread.currentThread().getName() + "]:销售:" + bread);
notFull.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
class Bread {
private String name;
public Bread(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
分享到:
相关推荐
【Java多线程编程】是Java开发中不可或缺的一部分,它允许程序同时执行多个任务,从而提高效率和响应速度。本文将深入探讨Java多线程的优缺点、创建方式以及线程安全与同步机制。 **一、多线程的优缺点** 1. **...
"浅谈Java多线程编程" 从标题和描述可以看出,这篇文章的主题是讨论Java多线程编程的相关知识点。 多线程编程的概念 Java语言的一个重要特点是支持多线程机制,这使得Java程序可以支持多程序并发执行,从而提高...
了解并熟练掌握这些Java多线程的概念和实践技巧,对于编写高性能、并发友好的Java应用至关重要。在实际开发中,合理地使用多线程可以提高程序的运行效率,但也需要考虑到线程安全、资源竞争等问题,避免出现死锁、...
"浅谈Java的多线程机制" 本文主要讨论了Java语言中的多线程机制,旨在提高应用程序的性能和实时控制性能。...本文对Java语言中的多线程机制进行了详细的讨论,为读者提供了一个系统的了解Java多线程编程模型的机会。
三、JAVA多线程机制的实现 JAVA的多线程机制使得编程人员可以很方便地开发出具有多线程功能、同时处理多个任务的应用。要编写安全高效的多线程程序,必须全面了解JAVA的多线程机制,掌握线程的控制方法。同时要解决...
Java多线程编程是Java开发中的重要组成部分,尤其对于大型应用程序和并发性能要求较高的系统而言。虽然Java在多线程方面可能不如C++灵活,但Java提供了强大的平台无关性和自动内存管理,使得开发者可以专注于并发...
内含 chapter02-chapter18 共 17 个实例性源码项目,内容循序渐进,由入门到精通。尤其适合于没有 Java 线程开发经验的朋友。自己动手敲出本资源解压缩后的 ...相信你理解了此源码之后,即可步入 Java 多线程开发。
Java多线程编程是Java语言中的一项高级特性,它允许同时运行多个线程来执行多个任务,以达到提高程序运行效率和用户体验的目的。Java 5 是在Java多线程编程中具有重要意义的一个版本,因为它对Java的并发API进行了...
_java多线程wait、notify机制详解_ 在Java多线程编程中,wait和notify是两个非常重要的机制,用于实现线程之间的通信和同步。在本文中,我们将通过示例代码详细介绍Java多线程wait和notify的使用,帮助读者更好地...
当我们谈到在Spring中实现多线程,实际上是在讨论如何在Spring环境中创建、管理和协调并发执行的任务。这涉及到Java的并发API以及Spring对这些API的包装和扩展。 首先,让我们了解Java中的多线程基础。在Java中,...
在Java开发中,多线程技术是一项重要的编程技能,它允许同时运行两个或多个部分,这些部分称为线程,每个线程可以处理不同的任务。这不仅能够提高程序的执行效率,还能改善用户体验,因为多线程可以实现程序的异步...
"浅谈Java多线程处理中Future的妙用" 在Java多线程处理中,Future是一个非常重要的概念,它可以帮助我们更好地处理并发任务。Future是一个未来对象,里面保存着线程处理结果,它像一个提货凭证,拿着它你可以随时去...
总结起来,Java多线程中的`join()`方法用于线程间的同步,确保一个线程在另一个线程完成后再继续执行。线程的优先级则影响线程调度,但不是绝对的执行顺序保证。理解并熟练运用这些概念对于编写高效的并发程序至关...
浅谈Java多线程实现及同步互斥通讯 多线程实现方式: Java中的多线程实现方式共有两种:通过继承Thread类和通过实现Runnable接口。下面我们来详细了解这两种方式: 1. 通过继承Thread类来实现多线程: 通过继承...
在Java中,多线程是通过创建并运行多个线程来实现的,每个线程代表着进程中的一条独立控制流。Java线程是抢占式的,意味着线程的执行是由操作系统调度,根据优先级和当前状态决定。 【进程】是一个程序或应用的实例...
在Java多线程编程中,确保线程安全是非常重要的,尤其是当涉及到共享数据时。本文主要讨论了一个在处理Boolean常量时可能遇到的同步问题。在Java中,`synchronized`关键字用于控制并发访问,保证同一时刻只有一个...
Java多线程是一种编程技术,允许程序同时执行多个任务,从而提高资源利用率、简化程序设计并加快程序响应速度。在Java中,多线程通过创建线程对象来实现,每个线程代表程序中的一个独立执行流。 **资源利用率更好**...
Java 多线程返回结果方式详解 在 Java 中,获取多线程的返回结果是一件复杂的事情。今天,我们将介绍三种方式来获取多线程的返回结果。 第一种方法:使用 Runnable 实现类 在这个方法中,我们可以在 Runnable 的...