Java多线程的例子及synchronized关键字锁定对象的用法

简介:

该例子所应用场景:一个线程负责生产,多个线程(该例为3个)负责消费;生产者不断的往堆栈中加入数据,消费者不断的从堆栈中取数据。

代码如下:

package com.xs.mail.thread;

import java.util.ArrayList;
import java.util.List;

class Widget {
}

class WidgetMaker extends Thread {
	List<Widget> finishedWidgets = new ArrayList<Widget>();

	public void run() {
		try {
			while (true) {
				//每1秒钟生产一个Widget
				Thread.sleep(1000);// act busy
				Widget w1 = new Widget();
				// 也就是说需要5秒钟才能新产生一个Widget,这决定了一定要用notify而不是notifyAll
				// 因为上面两行代码不是同步的,如果用notifyAll则所有线程都企图冲出wait状态
				// 第一个线程得到了锁,并取走了Widget(这个过程的时间小于5秒,新的Widget还没有生成)
				// 并且解开了锁,然后第二个线程获得锁(因为用了notifyAll其他线程不再等待notify语句
				// ,而是等待finishedWidgets上的锁,一旦锁放开了,他们就会竞争运行),运行
				// finishedWidgets.remove(0),但是由于finishedWidgets现在还是空的,
				// 于是产生异常
				// ***********这就是为什么下面的那一句不能用notifyAll而是要用notify

				synchronized (finishedWidgets) {
					finishedWidgets.add(w1);
					finishedWidgets.notify(); // 这里只能是notify而不能是notifyAll
				}
			}
		} catch (InterruptedException e) {
		}
	}

	public Widget waitForWidget() {
		synchronized (finishedWidgets) {
			if (finishedWidgets.size() == 0) {
				try {
					System.out.println("暂停线程:" + Thread.currentThread().getName());
					finishedWidgets.wait();
				} catch (InterruptedException e) {
				}
			}
			return finishedWidgets.remove(0);
		}
	}
}

public class WidgetUser extends Thread {
	private WidgetMaker maker;

	public WidgetUser(String name, WidgetMaker maker) {
		super(name);
		this.maker = maker;
	}

	public void run() {
		while (true) {
			Widget w = maker.waitForWidget();
			System.out.println(getName() + " got a widget");
		}
	}

	public static void main(String[] args) {
		WidgetMaker maker = new WidgetMaker();
		maker.start();
		new WidgetUser("Tom", maker).start();
		new WidgetUser("Jack", maker).start();
		new WidgetUser("Marry", maker).start();
	}
}


目录
相关文章
|
2天前
|
安全 Java 编译器
java中类与对象回顾总结-2
java中类与对象回顾总结
14 3
|
2天前
|
Java 编译器
java中类与对象回顾总结-1
java中类与对象回顾总结
14 3
|
14小时前
|
安全 算法 Java
Java一分钟:线程同步:synchronized关键字
【5月更文挑战第11天】Java中的`synchronized`关键字用于线程同步,防止竞态条件,确保数据一致性。本文介绍了其工作原理、常见问题及避免策略。同步方法和同步代码块是两种使用形式,需注意避免死锁、过度使用导致的性能影响以及理解锁的可重入性和升级降级机制。示例展示了同步方法和代码块的运用,以及如何避免死锁。正确使用`synchronized`是编写多线程安全代码的核心。
9 2
|
1天前
|
Java
【JAVA基础篇教学】第五篇:Java面向对象编程:类、对象、继承、多态
【JAVA基础篇教学】第五篇:Java面向对象编程:类、对象、继承、多态
|
1天前
|
安全 Java
java-多线程学习记录
java-多线程学习记录
|
2天前
|
缓存 Java 程序员
关于创建、销毁对象⭐Java程序员需要掌握的8个编程好习惯
关于创建、销毁对象⭐Java程序员需要掌握的8个编程好习惯
关于创建、销毁对象⭐Java程序员需要掌握的8个编程好习惯
|
2天前
|
Java
从源码出发:JAVA中对象的比较
从源码出发:JAVA中对象的比较
10 3
|
2天前
|
Java
【Java多线程】面试常考 —— JUC(java.util.concurrent) 的常见类
【Java多线程】面试常考 —— JUC(java.util.concurrent) 的常见类
12 0
|
2天前
|
设计模式 消息中间件 安全
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
9 0
|
2天前
|
安全 Java 程序员
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
6 0