两个线程交叉打印递增数字,用synchronized和wait实现

       开启两个线程,一个线程打印1到100的奇数。如1,3,7…99. 另外一个线程打印1到100的偶数。如2,4,6…100. 
1到100的数字最终打印出来格式是1,2,3,4,5…100.** 

static int count = 0;
    static SingletonDemo1 s = new SingletonDemo1();
        
        public static void main(String[] args) {
            
            new Thread(new Runnable() {
                public void run() {
                    synchronized (s) {
                    while(count<=100) {
                            System.out.println(count++);
                            s.notify();
                        }
                        try {
                            s.wait();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            }).start();    
            
            
        new Thread(new Runnable() {
                
                @Override
                public void run() {
                    synchronized (s) {
                    while(count<=100) {
                            System.out.println(count++
                                    );
                            s.notify();
                            try {
                                s.wait();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                        
                        
                    }
                    
                }
            }).start();
        
            }


总结:

       1.wait和notify/notifyAll方法必须在在同步代码块中使用,为什么? 
java设计者为了避免wait和notify之间产生竞态条件,所以强制要求这样做,如果你不这么做,你的代码会抛出IllegalMonitorStateException异常。 
调用某个对象的wait()方法能让当前线程阻塞,前提是当前线程必须拥有此对象的锁,因此调用wait()方法必须在同步块或者同步方法中进行(synchronized块或者synchronized方法)。

       2.来实现线程间的通信,为什么wait、notify 和 notifyAll这些方法不在Thread类里面? 
我想主要原因是JAVA提供的锁是对象级的而不是线程级的,每个对象都有锁,通过线程获得。由于wait,notify和notifyAll都是锁级别的操作,所以把他们定义在Object类中因为锁属于对象。

       3.执行过程
s数组作为对象锁,thread 1首先进入synchronized的同步块中,thread 2阻塞在s的对象锁。thread 1进入while循环打印日志,执行s.notify方法,这里会唤醒等待s对象锁资源的线程,待thread 1执行完同步块的内容会自动释放锁资源接着打印日志,执行s.wait方法,thread 1交出当前的对象锁,阻塞在此,以至于后续的s end还未打印。 


        thread 2终于拿到了s锁资源,开始执行while,打印日志,执行s.notify方法,同样的唤醒thread 1,但得走完才能移交锁,接着打印日志,执行s.wait,thread 2阻塞在此,移交锁资源给thread 1。 thread 1接到资源后,从原来阻塞地点又开始运行了,打印s end日志,进入下一次循环…… 如此往复。 
        值得注意的是,调用notify或notifyAll方法后,当前线程并不会立即放弃锁的持有权,而必须要等待当前同步代码块执行完或者调用了wait方法才会让出锁资源。

猜你喜欢

转载自blog.csdn.net/qq_40531768/article/details/89336454
今日推荐