线程同步

时间:2012-08-21 09:47:11

标签: java multithreading synchronization

我正在开发一个我有3个线程的应用程序。 我们称他们为a,b,c。

现在我必须开发类似的东西。

最初b等待a完成任务,c等待b。

一旦'a'完成任务,它就会通知'b'。 'b'应该醒来。现在'a'进入等待状态。 'a'将等待'c'确认。

现在b完成任务并通知'c'。现在'c'醒来,'b'进入等待状态。

现在c完成任务并确认'a'。现在'c'就等了。

这是循环过程,并从 - >继续b,b - > c,c-> a

在此循环之间,所有线程都访问队列进行数据传输,即'a'将数据放入队列q1,'b'取出并放入另一个队列q2,'c'从q2取出并处理它并返回'一个“

我在实现此功能时遇到困难。 关于如何做到这一点的任何想法?

...谢谢

3 个答案:

答案 0 :(得分:1)

如果您被允许使用队列(看起来似乎是家庭作业),那么您可以做一些更优雅的事情。可能由此产生的内部锁定类似于具有信号量的解决方案,但更优雅。

创建3个队列,每对进程一个队列。他们不发送真实数据,只发送信号。

Queue<Integer> queueA2B = new BlockingQueue<Integer>();
Queue<Integer> queueB2C = new BlockingQueue<Integer>();
Queue<Integer> queueC2A = new BlockingQueue<Integer>();

// initialize only the queue that *feeds* A:

queueC2A.put(1);

每个进程必须从其队列中获取一个项目,执行其过程并向下一个发送信号。通过例子A:

while (...) {
   queueC2A.take(); // this will block until there's something in the queue
   // do my stuff
   queueA2B.put(1); // send "signal" to the next process
}

答案 1 :(得分:0)

很好的问题,我编写了一个小类,它将演示如何使用信号量来运行序列中的线程。希望这会有所帮助:

public class LockingDemo{

    private Semaphore a = new Semaphore(0);
    private Semaphore b = new Semaphore(0);
    private Semaphore c = new Semaphore(1);

    class A implements Runnable{
        @Override
        public void run() {
            try {
                c.acquire(1);
                System.out.println("Doing A");
                a.release(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    class B implements Runnable{
        @Override
        public void run() {
            try{
                a.acquire(1);
                System.out.println("Doing B");
                b.release(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    class C implements Runnable{
        @Override
        public void run() {
            try{
                b.acquire(1);
                System.out.println("Doing C");
                c.release(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }



    public void a() throws InterruptedException{
        new Thread(new A()).start();
    }

    public void b() throws InterruptedException{
        new Thread(new B()).start();
    }

    public void c() throws InterruptedException{
        new Thread(new C()).start();
    }

    public static void main(String[] args) throws InterruptedException {
        LockingDemo ld = new LockingDemo();
        System.out.println("FIRST RUN CALLING B -> A -> C");
        ld.b();
        ld.a();
        ld.c();
        Thread.currentThread().sleep(2000);
        System.out.println("SECOND RUN CALLING C -> B -> A");
        ld.c();
        ld.b();
        ld.a();
    }
}

这是OUTPUT

FIRST RUN CALLING B -> A -> C
Doing A
Doing B
Doing C
SECOND RUN CALLING C -> B -> A
Doing A
Doing B
Doing C

答案 2 :(得分:0)

我会用信号量来做。线程需要自己的信号量,完成后释放下一个信号量。您当然也可以使用监视器(Object#wait() and Object#notify())执行此操作。为了确保它们以循环方式运行,你只需让它们在无限循环中运行并等待信号量被填充:

import java.util.concurrent.Semaphore;

public class Main {
    private Semaphore a = new Semaphore(1), b = new Semaphore(0), c = new Semaphore(0);

    public class A implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    a.acquire(1);
                    Thread.sleep((long) (Math.random() * 1000));
                    System.out.println("performing task A");
                    b.release(1);
                } catch (InterruptedException e) {}
            }
        }
    }

    public class B implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    b.acquire(1);
                    Thread.sleep((long) (Math.random() * 1000));
                    System.out.println("performing task B");
                    c.release(1);
                } catch (InterruptedException e) {}
            }
        }
    }

    public class C implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    c.acquire(1);
                    Thread.sleep((long) (Math.random() * 1000));
                    System.out.println("performing task C");
                    a.release(1);
                } catch (InterruptedException e) {}
            }
        }
    }

    public void startThreads() {
        new Thread(new A()).start();
        new Thread(new B()).start();
        new Thread(new C()).start();
    }

    public static void main(String[] args) throws InterruptedException {
        Main ld = new Main();
        ld.startThreads();
    }
}

与显示器相比,这个解决方案的一个很酷的事情是你可以简单地从外面填充一个信号量,开始第二个“线程蠕虫”在圈子里运行。