如何在两个线程之间共享变量

时间:2010-03-17 22:35:01

标签: java multithreading design-patterns

我只是继承了一些代码,这段代码中的两个线程需要执行一个系统任务。一个线程应该在另一个线程之前执行系统任务。他们不应该一起执行系统任务。这两个线程没有相互引用。

现在,我知道我可以使用某种信号量来实现这一目标。但我的问题是让两个线程都能访问这个信号量的正确方法。

我可以创建一个新的静态变量/方法:

public class SharedSemaphore
{
    private static Semaphore s = new Semaphore (1, true);

    public static void acquire () {
        s.acquire();
    }

    public static void release () {
        s.release();
    }
}

这会起作用(对吗?)但这似乎不是正确的做法。因为,线程现在可以访问信号量,而无需引用它。这种事情似乎不是一个好的编程实践。我错了吗?

更新

我重新命名了两个方法performTask来获取,另一个方法被释放,因为我觉得这会分散实际问题。

3 个答案:

答案 0 :(得分:2)

我认为,你可以制作performSystemTask方法synchronized,这就足够了。

答案 1 :(得分:0)

如果线程应该一个接一个地运行,他们需要一个管理器。我会将它们包装到另一个类中,甚至是另一个线程类。

public class wrapperThread extends Thread {
    public void run() {
        Worker1Thread myThread = new Worker1Thread();
        myThread.start();
        myThread.join();
        Worker2Thread myThread = new Worker2Thread();
        myThread.start();
        myThread.join();
    }
}

这是我能想到的最安全,最干净的方式。

如果它们根本不应该同时运行,那么它们应该是同一个线程。

答案 2 :(得分:0)

我看到你让你的信号量变得公平。所以我想你关心订单执行这些“系统任务”?然后,在我看来,依靠线程的有序到达是非常脆弱和危险的。如果您使用synchronized关键字,也会出现此问题。

我说你应该使用CountdownLatch代替。

class TaskOrganizer {
    private final CountdownLatch firstTask = new CountdownLatch(1);

    public void firstTaskIsDone(){
        firstTask.countDown();
    }

    public void permissionForSecondaryTask(){
        firstTask.await();
    }
}

如果你不能将TaskOrganizer个对象传递给你的线程,那么我想让它静态是可以的,但通常最好将实例传递给你的线程(好吧,确切地说是Runnables)。你永远不知道你是否需要2个TaskOrganizers。如果您使用过static,那么事情就不会像以前那样干净。

我猜这很明显,但是一个线程调用firstTaskIsDone(),另一个线程阻塞直到完成,调用permissionForSecondaryTask();。如果你有大量的任务来组织大量的线程,你可能想推出Phaser(计划出现在JDK 7中,后端可用http://gee.cs.oswego.edu/dl/concurrency-interest/)。