как разделить переменную между двумя потоками - PullRequest
1 голос
/ 18 марта 2010

Я просто унаследовал некоторый код, два потока в этом коде должны выполнять системную задачу. Один поток должен выполнить системную задачу перед другим потоком. Они не должны выполнять системную задачу вместе. Два потока не имеют ссылок друг на друга.

Теперь я знаю, что могу использовать какой-то семафор для достижения этой цели. Но мой вопрос в том, как правильно получить доступ к семафору для обоих потоков.

Я мог бы создать статическую переменную / метод нового класса:

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

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

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

Это бы сработало (верно?), Но это не похоже на то, что нужно делать. Потому что теперь потоки имеют доступ к семафору, даже не имея на него ссылки. Подобные вещи не кажутся хорошей практикой программирования. Я не прав?

UPDATE:

Я переименовал два метода, которые нужно выполнить перфомансом, а другой - выпустить, потому что я чувствовал, что это отвлекает от самого вопроса.

Ответы [ 3 ]

2 голосов
/ 18 марта 2010

Я думаю, вы можете сделать performSystemTask метод synchronized и этого будет достаточно.

0 голосов
/ 18 марта 2010

Я вижу, что вы сделали свой Семафор честным. Итак, я думаю, что вы заботитесь о порядке , эти "системные задачи" выполняются? Тогда полагаться на заказанные поступления нитей очень хрупко и опасно, на мой взгляд. Эта проблема также будет присутствовать, если вы используете ключевое слово synchronized.

Я бы сказал, что вы должны использовать CountdownLatch вместо этого.

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

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

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

Если вы не можете передать TaskOrganizer объекты в ваши потоки, тогда я думаю, что делать это статично - это нормально, но обычно лучше передавать экземпляры вашим потокам (ну, точнее, в Runnables). Вы никогда не знаете, если вам понадобятся 2 TaskOrganizer. Если бы вы использовали static, то все будет не так чище, как могло бы быть.

Полагаю, это очевидно, но один поток вызывает firstTaskIsDone(), а другой блокирует, пока это не будет сделано, вызывая permissionForSecondaryTask();. Если у вас есть тонны задач для организации с тоннами потоков, вы можете развернуть Phaser (запланировано появиться в JDK 7, бэкпорт доступен на http://gee.cs.oswego.edu/dl/concurrency-interest/).

0 голосов
/ 18 марта 2010

Если потоки всегда должны запускаться один за другим, им нужен менеджер. Я бы обернул их в другой класс, даже в другой класс потока.

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

Это самый безопасный и чистый способ, который я могу себе представить.

Если они просто никогда не должны запускаться в одно и то же время, то, вероятно, они должны быть одного потока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...