`

小谈java多线程

    博客分类:
  • java
阅读更多

关键字: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;
	}
}
 

 

0
2
分享到:
评论

相关推荐

    浅谈java多线程编程

    【Java多线程编程】是Java开发中不可或缺的一部分,它允许程序同时执行多个任务,从而提高效率和响应速度。本文将深入探讨Java多线程的优缺点、创建方式以及线程安全与同步机制。 **一、多线程的优缺点** 1. **...

    浅谈Java多线程编程.pdf

    "浅谈Java多线程编程" 从标题和描述可以看出,这篇文章的主题是讨论Java多线程编程的相关知识点。 多线程编程的概念 Java语言的一个重要特点是支持多线程机制,这使得Java程序可以支持多程序并发执行,从而提高...

    浅谈JAVA中多线程的实现.zip

    了解并熟练掌握这些Java多线程的概念和实践技巧,对于编写高性能、并发友好的Java应用至关重要。在实际开发中,合理地使用多线程可以提高程序的运行效率,但也需要考虑到线程安全、资源竞争等问题,避免出现死锁、...

    浅谈Java的多线程机制.pdf

    本文旨在探讨Java多线程机制的细节,并且深入解析其在提升程序性能方面的优势与实现方法。 ### 多线程编程的重要性 在计算机的发展史上,多核处理器的普及使得传统的单线程处理方式不再能够充分挖掘CPU的潜力。多...

    浅谈JAVA语言的多线程技术.pdf

    三、JAVA多线程机制的实现 JAVA的多线程机制使得编程人员可以很方便地开发出具有多线程功能、同时处理多个任务的应用。要编写安全高效的多线程程序,必须全面了解JAVA的多线程机制,掌握线程的控制方法。同时要解决...

    Java多线程编程经验谈

    Java多线程编程是Java开发中的重要组成部分,尤其对于大型应用程序和并发性能要求较高的系统而言。虽然Java在多线程方面可能不如C++灵活,但Java提供了强大的平台无关性和自动内存管理,使得开发者可以专注于并发...

    Java 多线程编程入门到精通源代码.zip

    内含 chapter02-chapter18 共 17 个实例性源码项目,内容循序渐进,由入门到精通。尤其适合于没有 Java 线程开发经验的朋友。自己动手敲出本资源解压缩后的 ...相信你理解了此源码之后,即可步入 Java 多线程开发。

    java多线程编程总结.pdf

    Java多线程编程是Java语言中的一项高级特性,它允许同时运行多个线程来执行多个任务,以达到提高程序运行效率和用户体验的目的。Java 5 是在Java多线程编程中具有重要意义的一个版本,因为它对Java的并发API进行了...

    浅谈java多线程wait,notify

    _java多线程wait、notify机制详解_ 在Java多线程编程中,wait和notify是两个非常重要的机制,用于实现线程之间的通信和同步。在本文中,我们将通过示例代码详细介绍Java多线程wait和notify的使用,帮助读者更好地...

    java中spring里实现多线程

    当我们谈到在Spring中实现多线程,实际上是在讨论如何在Spring环境中创建、管理和协调并发执行的任务。这涉及到Java的并发API以及Spring对这些API的包装和扩展。 首先,让我们了解Java中的多线程基础。在Java中,...

    浅谈JAVA中多线程的实现.pdf

    在Java开发中,多线程技术是一项重要的编程技能,它允许同时运行两个或多个部分,这些部分称为线程,每个线程可以处理不同的任务。这不仅能够提高程序的执行效率,还能改善用户体验,因为多线程可以实现程序的异步...

    浅谈Java多线程处理中Future的妙用(附源码)

    "浅谈Java多线程处理中Future的妙用" 在Java多线程处理中,Future是一个非常重要的概念,它可以帮助我们更好地处理并发任务。Future是一个未来对象,里面保存着线程处理结果,它像一个提货凭证,拿着它你可以随时去...

    浅谈java多线程 join方法以及优先级方法

    总结起来,Java多线程中的`join()`方法用于线程间的同步,确保一个线程在另一个线程完成后再继续执行。线程的优先级则影响线程调度,但不是绝对的执行顺序保证。理解并熟练运用这些概念对于编写高效的并发程序至关...

    浅谈Java多线程实现及同步互斥通讯

    浅谈Java多线程实现及同步互斥通讯 多线程实现方式: Java中的多线程实现方式共有两种:通过继承Thread类和通过实现Runnable接口。下面我们来详细了解这两种方式: 1. 通过继承Thread类来实现多线程: 通过继承...

    浅谈多线程_让程序更高效的运行

    在Java中,多线程是通过创建并运行多个线程来实现的,每个线程代表着进程中的一条独立控制流。Java线程是抢占式的,意味着线程的执行是由操作系统调度,根据优先级和当前状态决定。 【进程】是一个程序或应用的实例...

    浅谈Java多线程编程中Boolean常量的同步问题

    在Java多线程编程中,确保线程安全是非常重要的,尤其是当涉及到共享数据时。本文主要讨论了一个在处理Boolean常量时可能遇到的同步问题。在Java中,`synchronized`关键字用于控制并发访问,保证同一时刻只有一个...

    浅谈Java多线程的优点及代码示例

    Java多线程是一种编程技术,允许程序同时执行多个任务,从而提高资源利用率、简化程序设计并加快程序响应速度。在Java中,多线程通过创建线程对象来实现,每个线程代表程序中的一个独立执行流。 **资源利用率更好**...

    浅谈Java获得多线程的返回结果方式(3种)

    Java 多线程返回结果方式详解 在 Java 中,获取多线程的返回结果是一件复杂的事情。今天,我们将介绍三种方式来获取多线程的返回结果。 第一种方法:使用 Runnable 实现类 在这个方法中,我们可以在 Runnable 的...

Global site tag (gtag.js) - Google Analytics