3个人玩游戏一台手柄游戏,一次只能有一个人玩 示例代码1
public class Player implements Runnable {
private final int id;
private Game game;
public Player(int id, Game game) {
this.id = id;
this.game = game;
}
public String toString() {
return "Athlete<" + id + ">";
}
public int hashCode() {
return new Integer(id).hashCode();
}
public void playGame() throws InterruptedException{
System.out.println(this.toString() + " ready!");
game.play(this);
}
public void run() {
try {
playGame();
} catch (InterruptedException e) {
System.out.println(this + " quit the game");
}
}
}
public class Game implements Runnable {
private boolean start = false;
public void play(Player player) throws InterruptedException {
synchronized (this) {
System.out.println(player.toString()+"获得锁");
while (!start){
System.out.println(player.toString()+"在等待");
wait();
System.out.println( player.toString()+"被唤醒了");
}
if (start)
System.out.println(player + " have played!");
}
}
//通知所有玩家
public synchronized void beginStart() {
start = true;
notifyAll();
}
public void run() {
start = false;
System.out.println("Ready......");
System.out.println("Ready......");
System.out.println("game start");
beginStart();//通知所有玩家游戏准备好了
}
public static void main(String[] args) throws InterruptedException {
Set<Player> players = new HashSet<Player>();
//实例化一个游戏
Game game = new Game();
//实例化3个玩家
for (int i = 0; i < 3; i++)
players.add(new Player(i, game));
//启动3个玩家
Iterator<Player> iter = players.iterator();
while (iter.hasNext())
new Thread(iter.next()).start();
Thread.sleep(100);
//游戏启动
new Thread(game).start();
}
}
执行结果:
Athlete<0> ready!
Athlete<1> ready!
Athlete<2> ready!
Athlete<0>获得锁
Athlete<0>在等待
Athlete<2>获得锁
Athlete<2>在等待
Athlete<1>获得锁
Athlete<1>在等待
Ready......
Ready......
game start
Athlete<1>被唤醒了
Athlete<1> have played!
Athlete<2>被唤醒了
Athlete<2> have played!
Athlete<0>被唤醒了
Athlete<0> have played!
游戏对象game只有1个,synchronized (this)锁的实际就是game对象, 三个玩家线程都依次得到锁并在wait等待时释放锁。启动游戏线程时,通知所有线程,三个玩家线程需要竞争同步锁,得到同步锁的线程执行完synchronized(this)代码块后,自动释放同步锁,处于同步锁阻塞的剩下的2个线程再次竞争,直至都执行完毕。
总结:
wait()会释放锁,下一次被唤醒并获得锁时,会紧接着wait的下一行开始执行。
obj.notifyAll()是唤醒所有在obj上等待的线程,但是notifyAll 不会释放锁,执行完synchronized 代码块时,才会释放锁。(注意:obj.notifyAll()只是唤醒所有在obj上等待的线程,并不会唤醒应用中无关的线程)
notify()是通知一个线程,notifyAll()时通知所有线程,如果上面的例子beginStart方法的notifyAll()改为notify,那么就只有一个人能玩游戏,wait状态的线程如果没被唤醒,会一直的等待,即使锁没被占用。
wait() notify() notifyAll()方法必须写在同步方法或者同步块之内,并且同步的锁必须与调用等待方法和通知方法是同一个对象(比如:synchronized(obj1){},那么调用等待方法的也必须是obj1),否则会报java.lang.IllegalMonitorStateException异常,就是因为没有拥有锁导致的。例如上例的beginStart方法,去掉synchronized ,就会报这个错误。
用三个线程打印出连续10次的ABC,要求1个线程打A,1个线程打B,1个线程打C, 示例代码:
public class PrintABC {
public static Boolean isThreadA = true;
public static Boolean isThreadB = false;
public static Boolean isThreadC = false;
public static void main(String[] args) {
final PrintABC abc = new PrintABC();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (abc) {
while(!isThreadA) {
try {
abc.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.print("A");
isThreadA = false;
isThreadB = true;
isThreadC = false;
abc.notifyAll();
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (abc) {
while(!isThreadB) {
try {
abc.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.print("B");
isThreadA = false;
isThreadB = false;
isThreadC = true;
abc.notifyAll();
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (abc) {
while(!isThreadC) {
try {
abc.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.print("C");
isThreadA = true;
isThreadB = false;
isThreadC = false;
abc.notifyAll();
}
}
}
}).start();
}
}
执行结果:
ABCABCABCABCABCABCABCABCABCABC
abc对象是三个线程共同的锁,存在竞争。for循环中刚好可以使每个字母打印10次,for循环每次都需要竞争abc锁,竞争得到abc锁时,条件不符合则等待并释放锁,让其他线程竞争,条件符合则打印字母,打印完成后,会通知所有的线程,在执行完synchronized 块时,会释放锁。
注意:notifyAll 和wait方法的调用对象是锁,所以写成abc.notifyAll();abc.wait(); 3人玩游戏的那个例子,之所以能不写调用的对象,是因为锁就是this ,不写也是等价。
public class Player implements Runnable {
private final int id;
private Game game;
public Player(int id, Game game) {
this.id = id;
this.game = game;
}
public String toString() {
return "Athlete<" + id + ">";
}
public int hashCode() {
return new Integer(id).hashCode();
}
public void playGame() throws InterruptedException{
System.out.println(this.toString() + " ready!");
game.play(this);
}
public void run() {
try {
playGame();
} catch (InterruptedException e) {
System.out.println(this + " quit the game");
}
}
}
public class Game implements Runnable {
private boolean start = false;
public void play(Player player) throws InterruptedException {
synchronized (this) {
System.out.println(player.toString()+"获得锁");
while (!start){
System.out.println(player.toString()+"在等待");
wait();
System.out.println( player.toString()+"被唤醒了");
}
if (start)
System.out.println(player + " have played!");
}
}
//通知所有玩家
public synchronized void beginStart() {
start = true;
notifyAll();
}
public void run() {
start = false;
System.out.println("Ready......");
System.out.println("Ready......");
System.out.println("game start");
beginStart();//通知所有玩家游戏准备好了
}
public static void main(String[] args) throws InterruptedException {
Set<Player> players = new HashSet<Player>();
//实例化一个游戏
Game game = new Game();
//实例化3个玩家
for (int i = 0; i < 3; i++)
players.add(new Player(i, game));
//启动3个玩家
Iterator<Player> iter = players.iterator();
while (iter.hasNext())
new Thread(iter.next()).start();
Thread.sleep(100);
//游戏启动
new Thread(game).start();
}
}
执行结果:
Athlete<0> ready!
Athlete<1> ready!
Athlete<2> ready!
Athlete<0>获得锁
Athlete<0>在等待
Athlete<2>获得锁
Athlete<2>在等待
Athlete<1>获得锁
Athlete<1>在等待
Ready......
Ready......
game start
Athlete<1>被唤醒了
Athlete<1> have played!
Athlete<2>被唤醒了
Athlete<2> have played!
Athlete<0>被唤醒了
Athlete<0> have played!
游戏对象game只有1个,synchronized (this)锁的实际就是game对象, 三个玩家线程都依次得到锁并在wait等待时释放锁。启动游戏线程时,通知所有线程,三个玩家线程需要竞争同步锁,得到同步锁的线程执行完synchronized(this)代码块后,自动释放同步锁,处于同步锁阻塞的剩下的2个线程再次竞争,直至都执行完毕。
总结:
wait()会释放锁,下一次被唤醒并获得锁时,会紧接着wait的下一行开始执行。
obj.notifyAll()是唤醒所有在obj上等待的线程,但是notifyAll 不会释放锁,执行完synchronized 代码块时,才会释放锁。(注意:obj.notifyAll()只是唤醒所有在obj上等待的线程,并不会唤醒应用中无关的线程)
notify()是通知一个线程,notifyAll()时通知所有线程,如果上面的例子beginStart方法的notifyAll()改为notify,那么就只有一个人能玩游戏,wait状态的线程如果没被唤醒,会一直的等待,即使锁没被占用。
wait() notify() notifyAll()方法必须写在同步方法或者同步块之内,并且同步的锁必须与调用等待方法和通知方法是同一个对象(比如:synchronized(obj1){},那么调用等待方法的也必须是obj1),否则会报java.lang.IllegalMonitorStateException异常,就是因为没有拥有锁导致的。例如上例的beginStart方法,去掉synchronized ,就会报这个错误。
用三个线程打印出连续10次的ABC,要求1个线程打A,1个线程打B,1个线程打C, 示例代码:
public class PrintABC {
public static Boolean isThreadA = true;
public static Boolean isThreadB = false;
public static Boolean isThreadC = false;
public static void main(String[] args) {
final PrintABC abc = new PrintABC();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (abc) {
while(!isThreadA) {
try {
abc.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.print("A");
isThreadA = false;
isThreadB = true;
isThreadC = false;
abc.notifyAll();
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (abc) {
while(!isThreadB) {
try {
abc.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.print("B");
isThreadA = false;
isThreadB = false;
isThreadC = true;
abc.notifyAll();
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (abc) {
while(!isThreadC) {
try {
abc.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.print("C");
isThreadA = true;
isThreadB = false;
isThreadC = false;
abc.notifyAll();
}
}
}
}).start();
}
}
执行结果:
ABCABCABCABCABCABCABCABCABCABC
abc对象是三个线程共同的锁,存在竞争。for循环中刚好可以使每个字母打印10次,for循环每次都需要竞争abc锁,竞争得到abc锁时,条件不符合则等待并释放锁,让其他线程竞争,条件符合则打印字母,打印完成后,会通知所有的线程,在执行完synchronized 块时,会释放锁。
注意:notifyAll 和wait方法的调用对象是锁,所以写成abc.notifyAll();abc.wait(); 3人玩游戏的那个例子,之所以能不写调用的对象,是因为锁就是this ,不写也是等价。
发表评论
-
线程状态
2016-12-29 17:05 423线程在一定条件下,状 ... -
java中中synchronized的用法详解
2016-12-13 16:43 10961.对象锁: 1.1对象锁是run方法所在类的实例 s ... -
compareTo
2016-12-09 16:24 456compareTo是按字典顺序比较两个字符串。该比较基于字符串 ... -
集合(放对象)排序
2016-12-09 15:37 453//转载:http://blog.csdn.net/zxy_s ... -
MyEclipse提示“错误: 找不到或无法加载主类”-转载
2016-07-18 10:44 1465转载:http://www.ithao123.cn/conte ... -
java复制的实现方式比较(clone,序列化)
2014-07-27 19:44 609java对象的复制 方式1:clone 所需操作:实现Clo ... -
集合的复制
2014-07-27 19:32 477//示例 //学生类 package com.softst ... -
数组的copy
2014-07-27 19:28 389package com.softstome.clone.arr ... -
深层复制与浅层复制(通过序列化的方式实现)
2014-07-27 19:23 889package com.softstome.clone.arr ... -
深层复制与浅层复制(通过clone的方式)
2014-07-27 19:12 791深层复制与浅层复制 深 ...
相关推荐
源码—Java多线程5—死锁和wait notify notifyAll
总结一下,`wait()`, `notify()`, 和 `notifyAll()` 是Java多线程编程中的核心工具,它们与`synchronized`关键字一起,为线程间的协作提供了强大的支持。理解并熟练掌握这些概念,对于编写高效、安全的多线程程序至...
总结来说,Java的 `wait()` 和 `notify()` 提供了一种在多线程环境中控制线程执行的机制。通过合理使用这些方法,我们可以实现线程间的协作,精确控制子线程的运行状态。然而,这种方式虽然灵活,但管理起来相对复杂...
在本文中,我们将通过示例代码详细介绍Java多线程wait和notify的使用,帮助读者更好地理解和掌握这两个机制。 wait机制 在Java中,wait机制用于暂停当前线程的执行,并释放当前对象的锁,以便让其他线程获得锁并...
Java多线程中wait、notify、notifyAll使用详解 Java中多线程编程中,wait、notify、notifyAll三个方法是非常重要的,它们都是Object对象的方法,用于线程之间的通信。下面我们将详细介绍这三个方法的使用和作用。 ...
在Java多线程编程中,wait和notify是两个非常重要的方法,它们都是Object类的方法,用于线程之间的通信和同步。下面我们将详细解释wait和notify的用法。 wait方法 wait方法是Object类的一个方法,用于让当前线程...
Java中的多线程编程是构建高效并发应用的关键技术之一,其中`wait()`、`notify()`和`notifyAll()`是Java对象锁机制中的三个关键方法,它们位于`java.lang.Object`类中,主要用于线程间通信。本文将深入探讨`notify()...
总之,Java多线程同步通过wait()、notify()和notifyAll()等方法,配合synchronized关键字,实现了对共享资源的访问控制,保证了程序的正确性。同时,原子操作和volatile关键字提供了更细粒度的线程安全保证。理解并...
wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视。本文对这些关键字的使用进行了描述。 在 Java 中可以用 wait、notify 和 notifyAll 来实现...
同样,当线程使用wait方法时,它会主动释放锁并进入等待状态,直到其他线程调用notify或notifyAll方法来唤醒它。此外,sleep方法可以使线程进入阻塞状态一段时间,而join方法则允许一个线程等待另一个线程完成其任务...
标题和描述概述的知识点主要集中在Java的多线程机制中,特别是`wait`和`notify`方法在同步锁中的应用。这些方法对于控制线程之间的交互至关重要,尤其是在资源有限或需要确保数据一致性的情况下。 ### Java同步锁...
学习《汪文君JAVA多线程编程实战》不仅能够提高读者对Java多线程编程的理解,还有助于培养良好的并发编程习惯,避免常见的并发陷阱。对于想要提升自己在并发编程领域技能的Java开发者来说,这本书无疑是一份宝贵的...
Java多线程是Java编程中的重要概念,尤其在如今的多核处理器环境下,理解并熟练掌握多线程技术对于提高程序性能和响应速度至关重要...通过对这些知识点的学习和实践,读者可以深入理解Java多线程的运用,提升编程技能。
3. **线程同步与并发控制**:论文会深入讲解JAVA中的线程同步机制,如synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口和ReentrantLock类的使用。此外,可能会探讨并发工具类,如Semaphore、...
在Java编程中,多线程并发是...总之,Java的多线程并发实例可以帮助我们更好地理解和实践线程控制、同步机制以及经典的设计模式,提升我们的编程能力。通过不断学习和实践,我们可以编写出高效、安全的多线程并发程序。
Java中,可以通过wait()、notify()和notifyAll()这三个Object类的方法来实现线程间的通信。这些方法必须在同步环境中使用,否则会抛出异常。此外,Java 5引入了BlockingQueue阻塞队列,它是一种线程安全的数据结构,...
Java多线程机制是Java编程中至关重要的一部分,它允许程序同时执行多个任务,提升应用程序的效率和响应性。以下是对各个知识点的详细说明: 9.1 Java中的线程: Java程序中的线程是在操作系统级别的线程基础上进行...
wait set——线程的休息室 wait方法——把线程放入wait set notify方法——从wait set拿出线程 notifyAll方法——从wait set拿出所有线程 wait、notify、notifyAll是Object类的方法 线程的状态移转 跟线程有关的其他...
为了在多线程中同步进度更新,我们可以利用synchronized关键字、wait()、notify()方法,或者使用Java并发库中的高级工具,如Semaphore、CyclicBarrier或CountDownLatch等。 一个简单的进度条实现可以采用共享变量...
Java提供了wait(), notify()和notifyAll()方法,这些方法用于在线程间交换信息,但必须在同步块中使用,以防止死锁和其他并发问题。此外,还有java.util.concurrent工具包,包含如BlockingQueue等高级并发结构,它们...