!!!!!!!!!!........................................
这三个东西,很容易,也很容易理解,几句话就轻松搞定了。
synchronized : 同一时刻只能有一个对象持有锁!
wait() : 当前线程会进入阻塞状态,并放弃锁
notify() :则会叫醒某一个线程
notifyAll():会叫醒所有线程
可是上面的理解对吗?
至少最后两个是错的。我原以为自己掌握的还好,可是今天遇到的这些状况却让我
不能自信的作出解释。
先看synchronized:
看下面这个例子,如果直接像下面一样通过一个SynTest对象调用,那么start这个锁就跟没加一样!
其实这个原因很简单,加锁的对象只能在一处使用,不管你是不是加锁对象本身,t1就是那个加锁的对象,它拥有那个锁,你可以无限的
调用它的加锁方法。
public class SynTest { public static void main(String[] args) { SynTest t1 = new SynTest(); for(int i = 0 ; i < 10; i++) { A a = t1.create(); t1.start(a); } } A create() { A a = new A(); return a; } class A implements Runnable { // SynTest t ; @Override public void run() { test(); // t.test(); (这里test加了synchronized) } // A(SynTest t) { // this.t = t; // } } public void test () { System.out.println(this); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void start(Runnable a) { new Thread(a).start(); } }
在看wait()和notify() / notifyAll() :
这两个东西我是误区颇深啊!
就像下面的代码,我还在一直想着,最后能够把所有的线程都唤醒了..
public class Test { public static void main(String[] args) throws InterruptedException { init(); while(!conns.isEmpty()) { Conn conn = conns.remove(0); conn.start(); Thread.sleep(100); } } static List<Conn> conns = new ArrayList<Conn> (); static void init() { conns.add(new Conn()); conns.add(new Conn()); conns.add(new Conn()); } static class Conn extends Thread { @Override public void run() { try { send(); response(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " get response" ); } public synchronized void send() throws InterruptedException { if(!conns.isEmpty()) { System.out.println(Thread.currentThread().getName() + " send A to Server"); wait(); } else { response(); } } public synchronized void response() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } notifyAll(); } } }
首先第一点,这两个东西必须方法在同步代码中,你可以给方法加synchronized 或者给 代码块加!
然后就是notify/notifyAll , 不是 A.notify() 或者 A.notifyAll() 就会把 B线程唤醒!!!!!
它是与对象挂钩,那个对象notify就只能notify那些等待这个对象控制权的线程!!!!
如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。 如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。 如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。
关于notify()/notifyAll()还要注意下下面这种情形:
当调用完了notify() / notifyAll() 的时候,并不等于等待线程就会立马运行,只有等调用完notify()或者notifyAll()
并退出synchronized块,释放对象锁后,其余线程才可获得锁执行。就像下面的例子,虽然调用了notifyAll()可是
线程阻塞在了,只有等他醒来,等待线程才能重新获得锁。
synchronized (flag) { flag = "true"; flag.notifyAll(); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } }
这篇博客 : notify / notifyAll / wait
相关推荐
`wait()`通常配合`notify()`/`notifyAll()`用于线程间的通信,`sleep()`则用于线程短暂休眠。 4) **阻塞队列实现**:`BlockingQueue`接口提供了线程安全的队列操作,如`ArrayBlockingQueue`、`LinkedBlockingQueue`...
DEF A notify() B wait() C notifyAll() D sleep() E.yield() F.synchronized(this) 7.构造BufferedInputStream的合适参数是哪个? AC A BufferedInputStream B BufferedOutputStream ...
Deadlocking can occur only when the wait(), notify(), and notifyAll() methods are used incorrectly. - 虽然这些方法的错误使用会导致死锁,但这并不是唯一的原因。 - E. It is possible for a single-...
- 多线程:Thread类,Runnable接口,同步机制(synchronized,wait(),notify(),notifyAll())。 - 内存管理:垃圾回收机制,堆和栈的区别,JVM内存模型。 2. **EJB方面.doc**:EJB(Enterprise JavaBeans)是...
42. `notify()`唤醒一个等待的线程,`notifyAll()`唤醒所有等待的线程。 43. `run()`直接执行,`start()`创建新线程并调用`run()`。 44. 创建线程池可使用`Executors`的静态工厂方法。 45. 线程池有RUNNING、...
實踐53:優先使用notifyAll()而非notify() 185 實踐54:針對wait()和notifyAll()使用旋鎖(spin locks) 187 實踐55:使用wait()和notifyAll()替換輪詢循環(polling loops) 191 實踐56:不要對locked object(㆖鎖...
- **Reversing wait() and notify():** Reversing the order of `obj.wait()` and `obj.notify()` might not cause the method to complete normally because `wait()` must be called within a synchronized block ...
4. **线程间的通信:** 使用`wait()`、`notify()`和`notifyAll()`等方法可以在线程间进行通信。 - `wait()`:使当前线程等待直到被其他线程唤醒或超时。 - `notify()`:随机唤醒一个等待线程。 - `notifyAll()`:...
- wait(), notify(), notifyAll():Object类的方法,用于线程间的通信,通常配合synchronized使用。 二、Java锁机制 1. **内置锁(显式锁)** - ReentrantLock(可重入锁):提供与synchronized相似的功能,但更...
- 多线程:线程的创建(Thread类和Runnable接口)、同步机制(synchronized关键字,wait(),notify(),notifyAll())。 - 文件和I/O流:文件读写、缓冲流、对象序列化和反序列化。 - 网络编程:Socket编程,TCP和...
- 线程状态:`sleep()`方法会使线程进入可中断的等待状态,`suspend()`方法已废弃,因为它可能导致死锁,`wait()`方法会让线程进入等待锁定池,等待被`notify()`或`notifyAll()`唤醒。`yield()`方法则会让当前线程...
wait(), notify()和notifyAll()方法被定义在Object类中,是因为Java设计者希望所有的对象都具备等待/通知的能力,任何对象都可以作为线程间的通信机制。 Thread类的sleep()和yield()方法是静态的,因为它们操作的是...
**为什么wait(), notify()和notifyAll()必须在同步方法或同步块中被调用** - 这些方法需要与锁的获取和释放配合使用,确保线程安全。 **Thread类中的yield方法的作用** - `yield()`方法让当前线程放弃CPU,让同...
而当生产者成功放入元素或者消费者成功取出元素后,它们会调用`notify()`或`notifyAll()`来唤醒等待的线程。 总的来说,"操作系统生产者与消费者问题Java简单模拟实现"这个项目提供了一个直观的多线程编程实例,...
线程间的同步和通信可通过synchronized关键字、wait()、notify()和notifyAll()等方法实现。 【Swing与JavaFX】 Swing和JavaFX是Java的图形用户界面(GUI)库,用于创建桌面应用。Swing是早期的选择,而JavaFX提供...
42. **notify()与notifyAll()的区别**:notify()唤醒一个等待该对象锁的线程;notifyAll()唤醒所有等待该对象锁的线程。 43. **线程的run()与start()的区别**:start()用于启动线程,让线程进入就绪状态;run()是...
Java提供了wait()、notify()和notifyAll()方法进行线程间的通信,但这需要在同步控制块(synchronized)中使用。Java 5引入了BlockingQueue阻塞队列,提供了一种更安全的线程间通信方式,如ArrayBlockingQueue、...
3. **线程同步**:避免多线程环境下的数据不一致,主要方法有synchronized关键字、wait()、notify()和notifyAll()。 4. **死锁**:当两个或多个线程互相等待对方释放资源而无法继续执行时,就会发生死锁。 5. **线程...
- 线程同步:synchronized关键字,wait()、notify()和notifyAll()方法,以及Lock接口。 - 线程池:ExecutorService和ThreadPoolExecutor的使用,线程池的配置与优化。 9. **网络编程** - Socket编程:客户端和...
这些机制在Object类中以wait(), notify()和notifyAll()方法的形式提供。这三个方法都是Java中所有对象的成员,因为它们定义在Object类中。 1. **wait()方法**: 当一个线程调用对象的wait()方法时,该线程会释放...