java - 已同步且线程未按预期工作

标签 java multithreading synchronized thread-sleep

我正在尝试做这样的事情:

有一个类Q,它有一个名为n的字段和两个方法put()get() 设置 n 的值或检索 n 的值。然后有两个类ProducerConsumerProducer 类有一个调用 put 的线程,consumer 类有一个调用 get 的线程。我正在尝试使用 Object lock 来同步它,它是 Singleton 类 LockClass 的唯一实例。

所以,这是我的类(class)问题:

public class Q {

    int n;

    public void put(int n){
        System.out.println("Put " + n);
        this.n = n;
    }

    public int get(){
        System.out.println("Got " + n);
        return n;
    }
}

锁类:

 public class LockClass {

        private static  Object Lock = new Object();

        private LockClass(){

        }


        public static Object getLock(){
            return Lock;
        }
    }

消费者:

public class Consumer implements Runnable {

    Thread t;
    Q q;


    public Consumer(Q q){
        this.q = q;
        t = new Thread(this);
        t.start();
    }
    /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true){

            synchronized(LockClass.getLock()){
                q.get();
            }
            try {
                System.out.println("Consumer slept");
                Thread.sleep(1000);
                System.out.println("Consumer awake");

            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

制作人:

public class Producer implements Runnable {

    Q q;
    Thread t;
    int i;

    public Producer(Q q){
        this.q = q;
        t = new Thread(this);
        t.start();
        i = 0;
    }
    /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true){
            i++;
            synchronized(LockClass.getLock()){
                q.put(i);
            }
            try {
                System.out.println("Producer slept");
                Thread.sleep(1000);
                System.out.println("Producer awake");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }


}

DemoClass:该类有主要功能

public class DemoClass {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Q q = new Q();

        Producer prod = new Producer(q);
        Consumer cons = new Consumer(q);
    }

}

所以,当我运行上面的代码时,我得到这样的结果:

Put 1
Producer slept
Got 1
Consumer slept
Consumer awake
Producer awake
Got 1
Consumer slept
Put 2
Producer slept
Consumer awake
Producer awake
Got 2
Consumer slept
Put 3
Producer slept
Consumer awake
Producer awake
Got 3
Consumer slept
Put 4
Producer slept

所以,我实际上让生产者和消费者中的线程都处于 hibernate 状态,以便有足够的时间进行上下文切换。现在,当两者需要同时 sleep 时,如果生产者先 sleep ,则它应该先醒来。但正如我在输出中看到的,生产者首先 sleep ,但消费者仍然首先醒来,并且无论哪个线程首先醒来都应该获得锁,因此另一个线程应该等待直到锁被释放。

为什么它没有按照我期望的方式工作?我错过了什么吗?

最佳答案

来自文档:

... However, these sleep times are not guaranteed to be precise, because they are limited by the facilities provided by the underlying OS... In any case, you cannot assume that invoking sleep will suspend the thread for precisely the time period specified

https://docs.oracle.com/javase/tutorial/essential/concurrency/sleep.html

关于java - 已同步且线程未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36909679/

相关文章:

javascript - 函数同步和可观察

java - 重新访问空同步块(synchronized block) : data visibility

java - 只有一种实现的接口(interface)

java - Android 线程上的 fragment 替换(...)

c# - 如何使用生产者/消费者队列递归搜索文件夹和文件?

multithreading - Delphi/Indy 多线程服务器

java - 如何为替代生产者和消费者方法编写 Java 多线程代码。它应该有 3 个生产者(P1、P2、P3)和 1 个消费者(C1)

java - 除法不使用数组长度 JAVA

java - Jawr CSSServlet 抛出 StackOverflowError

java - 了解 Java 中的引用行为