Обычная версия
Java форум JavaTalks
форум программистов

Поиск   Пользователи   Группы   Регистрация 
 Профиль   Личные сообщения 

 Вход 

Потоки и методы в них
Список форумов
 ->  Нити и процессы


 
Начать новую тему 
Предыдущая тема :: Следующая тема  
Автор Сообщение
LedFly : 4
Новичок

СообщениеЯнв 26, 2012 11:50 
Ответить с цитатой
Здравствуйте, такой вопрос: есть 2 потока, основной и Threader. Как из основного потока обратиться к методу Threader'а doSmth() так, чтобы он выполнился в потоке Threader, а не в основном?
Код:
public class Threader implements Runnable {

    private Thread t;

    public Threader() {
        t = new Thread(this);
        t.start();
    }

    public void doSmth() {       
      // Нужные действия
    }

    @Override
    public void run() {
        while (true){           
        }
    }
}
К началу Посмотреть профиль Отправить личное сообщение
LedFly : 4
Новичок

СообщениеЯнв 26, 2012 11:52 
Ответить с цитатой
ps. приложение юзает swing
К началу Посмотреть профиль Отправить личное сообщение
Skynin : 656
Постоянный посетитель

СообщениеЯнв 26, 2012 12:39 
Ответить с цитатой
Общий подход, внутри цикла что в run() опрашивается потокобезопасная очередь. В которую из другого потока помещается задание.

Либо, вы не держите поток, а создавайте каждый раз когда требуется вызвать doSmth(). С контролем чтобы не было одновременно запущено более 1го, если действия в doSmth() того требуют.

Swing же имеет штатные средства запуска кода в другом потоке - SwingWorker
К началу Посмотреть профиль Отправить личное сообщение
mesier : 693
Постоянный посетитель
Откуда: Новокузнецк

СообщениеФев 05, 2012 4:46 
Ответить с цитатой
LedFly писал(а):
Здравствуйте, такой вопрос: есть 2 потока, основной и Threader. Как из основного потока обратиться к методу Threader'а doSmth() так, чтобы он выполнился в потоке Threader, а не в основном?


Поллинг в потоке - не эффективно, так как грузит процессор..
Почему бы не воспользоваться механизмом wait-and-notify ?
Поток создается на этапе инициализации программы и сразу уходит "спать".
Из обработчика события Swing мы вызываем setDone(false). Потоку отправляется уведомление, он просыпается, отрабатывает один раз doSmth() и засыпает вновь..

Код:
public class Threader implements Runnable {

    private Thread t;

    private volatile boolean done = true;

    public Threader() {
        t = new Thread(this);
        t.start();
    }

    private void doSmth() {       
      // Нужные действия
    }

    @Override
    public synchronized void run() {
        while (true) {
           if (done) { 
               wait(); 
           }
           else { 
               doSmth();
               setDone(true);
           }
        }
    }

    public synchronized setDone(boolean d) {
        done = d;
        if (!done) {  notify();  }
    }

}
К началу Посмотреть профиль Отправить личное сообщение ICQ Number
escalade : 244
Новичок
Откуда: Kiev, Ukraine

СообщениеМар 14, 2012 18:50 
Ответить с цитатой
Ребята, работать с потоками на прямую это прошлый век. Работать нужно с задачами и экзекьютором. А также по необходимости с обьектами типа FutureTask. Нужно выполнить задачу в потоке, создал задачу (Runnable task) и закинул ее на выполнение в экзекьютор и все. Это очень просто.
К началу Посмотреть профиль Отправить личное сообщение
rfq : 213
Новичок

СообщениеМар 14, 2012 19:36 
Ответить с цитатой
LedFly писал(а):
Здравствуйте, такой вопрос: есть 2 потока, основной и Threader. Как из основного потока обратиться к методу Threader'а doSmth() так, чтобы он выполнился в потоке Threader, а не в основном?


Только договориться с Threader'ом по-хорошему, чтобы он исполнял ваши заявки. Завести очередь и чтобы он читал оттуда задания.

Код:
public class Threader implements Runnable {
   LinkedBlockingQueue<Request> queue=new LinkedBlockingQueue<Request>();

    public void doSmth(Request r) {       
      // Нужные действия
    }

    @Override
    public void run() {
        while (true){         
             doSmth(queue.take());
        }
    }
}
...

Threader threader;
threader.queue.add(new Request());
К началу Посмотреть профиль Отправить личное сообщение
rfq : 213
Новичок

СообщениеМар 14, 2012 19:44 
Ответить с цитатой
escalade писал(а):
Нужно выполнить задачу в потоке, создал задачу (Runnable task) и закинул ее на выполнение в экзекьютор и все. Это очень просто.

Закинуть задачу на исполнение во вновь созданном потоке точно также просто (new Thread(task).start()). Единственная разница в потреблении памяти под стеки.
К решению исходной задачи это не имеет отношения. В ней требуется а) выполнять действия в контексте конкретного экземпляра Threder'a и б) выполнять их последовательно, чтобы они не наезжали друг на друга.
К началу Посмотреть профиль Отправить личное сообщение
escalade : 244
Новичок
Откуда: Kiev, Ukraine

СообщениеМар 14, 2012 21:56 
Ответить с цитатой
Еще раз говорю, напрямую работать с потоками забудьте, все через экзекьюторы!

Создаем однопоточный ex:
Код:
ExecutorService singleExecutor = Executors.newSingleThreadExecutor();


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

Теперь создаем нужные задачи Runnable task и передаем на выполнение:
Код:
Future<?> futureTask = singleExecutor.submit(task);


При помощи обьекта futureTask, можно отслеживать состояние выполнения задачи futureTask.isDone() или отменить ее futureTask.cancel(false).

Все давно проверено. Very Happy
К началу Посмотреть профиль Отправить личное сообщение
rfq : 213
Новичок

СообщениеМар 15, 2012 7:12 
Ответить с цитатой
escalade писал(а):

При помощи обьекта futureTask, можно отслеживать состояние выполнения задачи futureTask.isDone() или отменить ее futureTask.cancel(false).

Все давно проверено. Very Happy


У экзекьюторов свои подводные камни. Например, исполнение future.get() блокирует поток экзекьютора, что может привести к дедлоку по типу "thread starvation". С обычными потоками такого не случается.
К началу Посмотреть профиль Отправить личное сообщение
escalade : 244
Новичок
Откуда: Kiev, Ukraine

СообщениеМар 15, 2012 8:04 
Ответить с цитатой
rfq писал(а):
escalade писал(а):

При помощи обьекта futureTask, можно отслеживать состояние выполнения задачи futureTask.isDone() или отменить ее futureTask.cancel(false).

Все давно проверено. Very Happy


У экзекьюторов свои подводные камни. Например, исполнение future.get() блокирует поток экзекьютора, что может привести к дедлоку по типу "thread starvation". С обычными потоками такого не случается.


future.get() не блокирует поток ex, он блокирует текущий поток в котором метод был вызван. Никаких дэдлоков.
А зачем вызывать future.get() в данном случае? Shocked
К началу Посмотреть профиль Отправить личное сообщение
rfq : 213
Новичок

СообщениеМар 15, 2012 9:12 
Ответить с цитатой
escalade писал(а):

future.get() не блокирует поток ex, он блокирует текущий поток в котором метод был вызван. Никаких дэдлоков.
А зачем вызывать future.get() в данном случае? Shocked

Если future.get() внутри таска, то текущий поток и есть поток экзекьютора.
Вызывают его для того, чтобы не циклить на future.done().
К началу Посмотреть профиль Отправить личное сообщение
escalade : 244
Новичок
Откуда: Kiev, Ukraine

СообщениеМар 15, 2012 10:34 
Ответить с цитатой
rfq писал(а):
escalade писал(а):

future.get() не блокирует поток ex, он блокирует текущий поток в котором метод был вызван. Никаких дэдлоков.
А зачем вызывать future.get() в данном случае? Shocked

Если future.get() внутри таска, то текущий поток и есть поток экзекьютора.
Вызывают его для того, чтобы не циклить на future.done().

Никто не вызывает future.get() внутри таска. Его в основном вызывают внешние потоки которым нужно блокирующим способом узнать завершилась ли задача и по возможности получить результат.
К началу Посмотреть профиль Отправить личное сообщение
diostm : 141
Новичок

СообщениеМар 15, 2012 10:45 
Ответить с цитатой
escalade писал(а):
rfq писал(а):
escalade писал(а):

future.get() не блокирует поток ex, он блокирует текущий поток в котором метод был вызван. Никаких дэдлоков.
А зачем вызывать future.get() в данном случае? Shocked

Если future.get() внутри таска, то текущий поток и есть поток экзекьютора.
Вызывают его для того, чтобы не циклить на future.done().

Никто не вызывает future.get() внутри таска. Его в основном вызывают внешние потоки которым нужно блокирующим способом узнать завершилась ли задача и по возможности получить результат.

+1
К началу Посмотреть профиль Отправить личное сообщение
 
Начать новую тему  Ответить на тему
Страница 1 из 1
Список форумов
 -> Нити и процессы


 
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Java and all Java-related trademarks and logos are trademarks or registered trademarks of Oracle Corporation in the United States and other countries.
Это сайт не относится к фирме Oracle Corporation и не поддерживается ею.

© 2006-2010 www.javatalks.ru: форум java программистов
Используется скрипт phpBB © 2001, 2010 phpBB Group

Хостинг от bizname.ru