Як викликати метод окремим потоком на Java?


126

скажімо, у мене є метод doWork(). Як я називаю це з окремої нитки (не з головної нитки).


На цьому нещодавно пов'язаному питанні трапляються приклади: вбивство нескінченної петлі в
Яві

stackoverflow.com/questions/36832094/… У мене є подібна проблема, будь ласка, допоможіть мені вирішити це
Sruthi Acg

Також вам може сподобатися поглянути на блог Реактивна Java.danlew.net/2014/09/15/grokking-rxjava-part-1 для асинхронних завдань
Натан Данн

Відповіді:


138

Створіть клас, який реалізує Runnableінтерфейс. Покладіть код, який потрібно запустити в run()методі - це метод, який ви повинні написати, щоб відповідати Runnableінтерфейсу. У своєму "головному" потоці створіть новий Threadклас, передавши конструктору екземпляр свого Runnable, а потім зателефонуйте start()на нього. startкаже JVM зробити магію для створення нової нитки, а потім викликає ваш runметод у цій новій нитці.

public class MyRunnable implements Runnable {

    private int var;

    public MyRunnable(int var) {
        this.var = var;
    }

    public void run() {
        // code in the other thread, can reference "var" variable
    }
}

public class MainThreadClass {
    public static void main(String args[]) {
        MyRunnable myRunnable = new MyRunnable(10);
        Thread t = new Thread(myRunnable)
        t.start();
    }    
}

Погляньте на підручник з питань конкурентоспроможності Java, щоб розпочати роботу.

Якщо ваш метод буде називатися часто, то, можливо, не варто кожного разу створювати нову нитку, оскільки це дорога операція. Напевно, найкраще використовувати якийсь пул потоків. Подивіться Future, Callable, Executorкласів в java.util.concurrentпакеті.


1
що робити, якщо є змінна, яку ви хотіли б передати?
Луї Ріс

8
run()Метод не приймає ніяких параметрів, так що ви не можете передати змінну там. Я б запропонував передати це в конструктор - я відредагую свою відповідь, щоб це показати.
Ноель М

1
Чи є короткий спосіб виклику 1 методу в інший потік? Я знаю new Thread() { public void run() {myMethod();}}.start();спосіб, це найкоротший?
Стівен Руз

@NoelM чи можете ви пояснити різницю між вашою та відповіді MANN?
Асиф Муштак

2
У відповіді MANN використовується анонімна реалізація Runnable- мій клас, який розширюється Runnable. І тому, що я це зробив, у мене є власний конструктор, який передає стан в об'єкт, що створюється.
Ноель М

183
Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        // code goes here.
    }
});  
t1.start();

або

new Thread(new Runnable() {
     @Override
     public void run() {
          // code goes here.
     }
}).start();

або

new Thread(() -> {
    // code goes here.
}).start();

або

Executors.newSingleThreadExecutor().execute(new Runnable() {
    @Override
    public void run() {
        myCustomMethod();
    }
});

або

Executors.newCachedThreadPool().execute(new Runnable() {
    @Override
    public void run() {
        myCustomMethod();
    }
});

Це прекрасно працювало для того, що я робив. Необхідно запустити веб-сервіс та оновити панель прогресу одночасно, використовуючи шаблон спостерігача.
dpi

@Ashish: Будь ласка, поясніть, що і чому було відредаговано?
MANN

1
@AshishAggarwal: Дивно мені здається, коли хтось робить це, не беручи дозволу автора!
MANN

@MANN чи можете ви пояснити, чому ви використовуєте метод запуску в параметрі Thread? якісь кращі показники?
Асиф Муштак

1
Чи потрібно нам явно припиняти нитку? Чи не існує ризику створення витоку пам’яті шляхом явного припинення потоку? Або нитка припиняється, коли це зроблено з run()?
вонив

59

У Java 8 це можна зробити за допомогою одного рядка коду.

Якщо ваш метод не приймає жодних параметрів, ви можете використовувати посилання на метод:

new Thread(MyClass::doWork).start();

В іншому випадку ви можете викликати метод у лямбда-виразі:

new Thread(() -> doWork(someParam)).start();

Вибачте, що поверніть це, але що саме ->означає?
Кайл

1
Це синтаксис, який використовується для створення виразу лямбда. Перегляньте ці посилання для отримання додаткової інформації: Що робить '->' у Java? , та Навчальні програми Java ™ - Lambda Expressions
Аарон Кон

@AaronCohn чудова людина! Чи знаєте ви альтернативи потокам на Java? Я родом із світу Python, де ми б використовували Celery task queueдля асинхронних речей
CESCO

У Java є абстракції вищого рівня для роботи з Threads , але, можливо, ви шукаєте щось подібне до Akka ?
Аарон Кон

8

Ще одним швидшим варіантом виклику речей (наприклад, DialogBoxes та MessageBoxes та створення окремих потоків для безпечних методів, що не стосуються потоків) буде використання Lamba Expression

  new Thread(() -> {
                      "code here"
            }).start();

3

Колись тому я написав простий клас утиліти, який використовує службу виконавця JDK5 та виконує конкретні процеси у фоновому режимі. Оскільки doWork () зазвичай має значення недійсного повернення, ви можете використовувати цей клас утиліти для його виконання у фоновому режимі.

Дивіться цю статтю, де я задокументував цю утиліту.


6
Майбутнє та позивний роблять подібні речі для вас.
Амір Афгані

Так. ідея полягає в тому, щоб абстрагувати інтерфейс за асинхронною обгорткою.
raja kolluru

Ланка розірвана (404).
palacsint

3

Щоб досягти цього за допомогою RxJava 2.x, ви можете використовувати:

Completable.fromAction(this::dowork).subscribeOn(Schedulers.io().subscribe();

У subscribeOn()методі визначає , який планувальник для запуску дії на - RxJava має низку визначених планувальників, в тому числі , Schedulers.io()який має пул потоки , призначені для операцій введення / виводу, і Schedulers.computation()яка призначена для процесорів інтенсивних операцій.


3

Якщо ви використовуєте принаймні Java 8, ви можете використовувати метод runAsyncз класу CompletableFuture

CompletableFuture.runAsync(() -> {...});

Якщо вам потрібно повернути результат, скористайтеся supplyAsyncнатомість

CompletableFuture.supplyAsync(() -> 1);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.