java 4 wątki

0

Cześć. Mam pytanie. Jeśli chcę uruchomić jedną metodę na 4 wątkach to jaka będzie poprawna implementacja?

public class Main extends Thread {
    public static void main(String[] args) {
        (new Thread(new Main())).start();
    }

    @Override
    public void run() {
        fillFile();
        fillFile();
        fillFile();
        fillFile();
    }

    public void fillFile() {
        //body
    }
}

czy też :

public class Main extends Thread {
    public static void main(String[] args) {
        (new Thread(new Main())).start();
        (new Thread(new Main())).start();
        (new Thread(new Main())).start();
        (new Thread(new Main())).start();
    }

    @Override
    public void run() {
        fillFile();
    }

    public void fillFile() {
        //body
    }
}
2

Jak chcesz uruchomić 4 wątki to musisz uruchomić 4 wątki, czyli drugi przykład. Przecież w pierwszym uruchamiasz tylko 1.

3

Warto implementować klasę Runnable zamiast dziedziczyć po Thread i taki obiekt przekazywać do konstruktora. To wygląda jaśniej np. w momencie używania klasy ThreadPoolExecutor.

0

Żadna z podanych, bo nie joinujesz tych wątków ani nic.

3

Przy wielu wątkach lepiej użyć ExecutorService, ale trzeba wtedy pamiętać o jego zamknięciu gdy nie jest już potrzebny:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {

    private static final int NUMBER_OF_TASKS = 4;

    public static void main(String[] args) {
        AtomicInteger threadCounter = new AtomicInteger(1);
        ExecutorService executor = Executors.newFixedThreadPool(
            NUMBER_OF_TASKS,
            runnable -> new Thread(runnable, "WorkerThread-" + threadCounter.getAndIncrement())
        );
        try {
            Stream.<Runnable>generate(() -> Main::doSomeWork)
                .limit(NUMBER_OF_TASKS)
                .map(executor::submit)
                .collect(Collectors.toList())
                .forEach(future -> {
                    try {
                        future.get();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                });
        } finally {
            executor.shutdown();
        }
    }

    private static void doSomeWork() {
        System.out.println("Doing some work in thread: " + Thread.currentThread().getName());
        try {
            Thread.sleep(ThreadLocalRandom.current().nextInt(5000));
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }
        System.out.println("Work done in thread: " + Thread.currentThread().getName());
    }
}

Można też użyć wbudowanego ForkJoinPool i parallel streama:

import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;

public class Main {

    private static final int NUMBER_OF_TASKS = 4;

    public static void main(String[] args) {
        IntStream.range(0, NUMBER_OF_TASKS)
            .parallel()
            .<Runnable>mapToObj(i -> Main::doSomeWork)
            .forEach(Runnable::run);
    }

    private static void doSomeWork() {
        System.out.println("Doing some work in thread: " + Thread.currentThread().getName());
        try {
            Thread.sleep(ThreadLocalRandom.current().nextInt(5000));
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }
        System.out.println("Work done in thread: " + Thread.currentThread().getName());
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1