繁体   English   中英

如何在另一个之前执行线程?

[英]How execute a thread before another?

我有一个小问题。

我有两个主题:

  • HelloThread - 打印“hello”五次。
  • GoodbyeThread - 五次打印“Goodbye”。

我想HelloThread运行GoodbyeThread运行GoodbyeThread运行。
我已经用信号量解决了这个问题(但信号量并不是真正的java方式,它更多的是C方式)。

HelloThread.java

    /*
     * To change this license header, choose License Headers in Project Properties.
     * To change this template file, choose Tools | Templates
     * and open the template in the editor.
     */
    package modifiedthreadhellogoodbye;

    import static java.lang.Thread.sleep;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import java.util.concurrent.Semaphore;

    class HelloThread implements Runnable {

        private final Object lock;
        //private final Semaphore lock;

        public HelloThread(Semaphore lock) {
            this.lock = lock;
        }

        public HelloThread(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            int pause;
            synchronized (lock) {
                for (int i = 0; i < 5; i++) {
                    System.out.println("Hello!");
                    pause = (int) (Math.random() * 1000);
                    try {
                        sleep(pause);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(HelloThread.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                lock.notifyAll();
                System.out.println("Outsite hello");
            }
                //lock.release();

        }
    }

GoodbyeThread.java

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package modifiedthreadhellogoodbye;

import static java.lang.Thread.sleep;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;

class GoodbyeThread implements Runnable {

    int pause;
    //private final Semaphore lock;
    private final Object lock;

    public GoodbyeThread(Semaphore lock) {
        this.lock = lock;
    }

    public GoodbyeThread(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock) {
            System.out.println("Inside the synchronized");
            try {
                lock.wait();
            } catch (InterruptedException ex) {
                Logger.getLogger(GoodbyeThread.class.getName()).log(Level.SEVERE, null, ex);
            }

            //lock.acquire();
            for (int i = 0; i < 5; i++) {
                System.out.println("Goodbye");
                pause = (int) (Math.random() * 1000);
                try {
                    sleep(pause);
                } catch (InterruptedException ex) {
                    Logger.getLogger(GoodbyeThread.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }

}

这是我的运行线程的类:

public class ModifiedThreadObject {

    private final Object lock = new Object();
    //private final Semaphore lock = new Semaphore(0);

    public ModifiedThreadObject() {
        HelloThread hello = new HelloThread(lock);
        GoodbyeThread goodbye = new GoodbyeThread(lock);

        Thread t1 = new Thread(hello);
        Thread t2 = new Thread(goodbye);
        t1.start();
        t2.start();
    }

}

主要想法是GoodbyeThread应该wait()来自HelloThread的信号。
如果GoodbyeThread运行GoodbyeThread ,它可以正常工作,但是HelloThread首先运行我有以下输出:

Hello!
Hello!
Hello!
Hello!
Hello!
Outsite hello
Inside the synchronized

HelloThread发送一个notifyAll() ,但没有人在等待,所以“信号”丢失了......

有人有想法吗?

首先,我在这里一直质疑单独线程的使用。 如果你想要一件事发生,只需使用一个线程。

但是,很容易等到一个线程完成 - 只需使用join

Thread t1 = new Thread(hello);
Thread t2 = new Thread(goodbye);
t1.start();
t1.join();
t2.start();

这样你就不需要在“hello”或“goodbye”代码中进行任何同步。

如果你想要更复杂的东西,我建议你查看java.util.concurrent包。 虽然您可以使用wait()notify() ,但通常使用更高级别的构造更好。 例如,对于生产者/消费者场景,您可能希望使用BlockingQueue而不是自己实现它。

您可以在CountDownLatch帮助下实现这一点,简单示例:

import java.util.concurrent.CountDownLatch;

public class Test {

    public static void main(String... s){

        final CountDownLatch cdl = new CountDownLatch(1);

        Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                int i = 5;
                while((i--)>0)
                    System.out.println("hello");
                cdl.countDown();
            }
        });


        Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    cdl.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("goodbye");
            }
        });

        t2.start();
        t1.start();
    }

}

虽然John Skeet提供了正确的方法来执行此类操作,但确切了解程序流错误也是有用的。

GoodbyeThread

synchronized (lock) {
    System.out.println("Inside the synchronized");
    try {
        lock.wait();
    }

那么,在获得锁定后,你坚持等待它? 问题是HelloThread已经在GoodbyeThread获取它时终止了; HelloThread调用notifyAll时,它什么也没做,因为还没有人在等待锁。


另一个问题是使用Semaphore 如上所述,您的类不使用Semaphore的任何功能,事实上,如果给出一个,它将把它转换为Object 你应该从你的代码中删除所有提到的Semaphore ,因为它是不必要的并且可能令人困惑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM