|
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(); }
}
} |
|
|
|
|
 |
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).
Все давно проверено.  |
|
|
|
 |
rfq : 213 Новичок
|
Мар 15, 2012 7:12 |
|
|
| escalade писал(а): |
При помощи обьекта futureTask, можно отслеживать состояние выполнения задачи futureTask.isDone() или отменить ее futureTask.cancel(false).
Все давно проверено.  |
У экзекьюторов свои подводные камни. Например, исполнение future.get() блокирует поток экзекьютора, что может привести к дедлоку по типу "thread starvation". С обычными потоками такого не случается. |
|
|
|
 |
escalade : 244 Новичок Откуда: Kiev, Ukraine
|
Мар 15, 2012 8:04 |
|
|
| rfq писал(а): |
| escalade писал(а): |
При помощи обьекта futureTask, можно отслеживать состояние выполнения задачи futureTask.isDone() или отменить ее futureTask.cancel(false).
Все давно проверено.  |
У экзекьюторов свои подводные камни. Например, исполнение future.get() блокирует поток экзекьютора, что может привести к дедлоку по типу "thread starvation". С обычными потоками такого не случается. |
future.get() не блокирует поток ex, он блокирует текущий поток в котором метод был вызван. Никаких дэдлоков.
А зачем вызывать future.get() в данном случае?  |
|
|
|
 |
rfq : 213 Новичок
|
Мар 15, 2012 9:12 |
|
|
| escalade писал(а): |
future.get() не блокирует поток ex, он блокирует текущий поток в котором метод был вызван. Никаких дэдлоков.
А зачем вызывать future.get() в данном случае?  |
Если future.get() внутри таска, то текущий поток и есть поток экзекьютора.
Вызывают его для того, чтобы не циклить на future.done(). |
|
|
|
 |
escalade : 244 Новичок Откуда: Kiev, Ukraine
|
Мар 15, 2012 10:34 |
|
|
| rfq писал(а): |
| escalade писал(а): |
future.get() не блокирует поток ex, он блокирует текущий поток в котором метод был вызван. Никаких дэдлоков.
А зачем вызывать future.get() в данном случае?  |
Если future.get() внутри таска, то текущий поток и есть поток экзекьютора.
Вызывают его для того, чтобы не циклить на future.done(). |
Никто не вызывает future.get() внутри таска. Его в основном вызывают внешние потоки которым нужно блокирующим способом узнать завершилась ли задача и по возможности получить результат. |
|
|
|
 |
diostm : 141 Новичок
|
Мар 15, 2012 10:45 |
|
|
| escalade писал(а): |
| rfq писал(а): |
| escalade писал(а): |
future.get() не блокирует поток ex, он блокирует текущий поток в котором метод был вызван. Никаких дэдлоков.
А зачем вызывать future.get() в данном случае?  |
Если future.get() внутри таска, то текущий поток и есть поток экзекьютора.
Вызывают его для того, чтобы не циклить на future.done(). |
Никто не вызывает future.get() внутри таска. Его в основном вызывают внешние потоки которым нужно блокирующим способом узнать завершилась ли задача и по возможности получить результат. |
+1 |
|
|
|
 |
|
|
Страница 1 из 1
|
Список форумов
-> Нити и процессы |
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
|
|