web-dev-qa-db-ja.com

スレッドを使用して2つの独立したタスクを同時に実行する

Javaのスレッドに関するチュートリアルをたくさん勉強しましたが、答えが見つかりません。

私の質問は、2つの独立したスレッドを同時に実行する方法ですか?

私の場合は次のとおりです。2つのタスクがあります。

  1. 一部のデータをデータベースに保存します
  2. モバイルデバイスでプッシュ通知を送信します。

これらの2つのタスクは独立しているので、同時に実行したいと思います。

2つのスレッドでスレッドプールを使用しようとしましたが、問題はデータベースタスクがすぐに終了することですが、プッシュ通知を送信するのに時間がかかります。

その結果、一方のタスクが終了し、もう一方のタスクがまだ保留中の場合、例外がスローされます。

また、スレッドを使用しなくても正常に実行されるため、コードに問題はありません。

前もって感謝します

10
S1LENT WARRIOR
_new Thread(new Runnable() {
    public void run() {
        System.out.println("Look ma, no hands");
    }
}).start();

new Thread(new Runnable() {
    public void run() {
        System.out.println("Look at me, look at me...");
    }
}).start();
_

うまく動作します...

ExecutorService を個人的に使用したいと思います。

ExecutorServiceの例で更新

だから私はこの本当に簡単な例を書きました...

基本的には、ExecutorServiceを使用していくつかの簡単なタスクを実行します。現状では、両方のタスクが互いに並行して実行されます(同時に)

_public static void main(String[] args) throws InterruptedException {
    ExecutorService service = Executors.newFixedThreadPool(2);
    service.submit(new PathScanner());
    service.submit(new Counter());

    service.shutdown();
    service.awaitTermination(1, TimeUnit.DAYS);

    System.exit(0);
}

public static class PathScanner implements Callable<Object> {

    @Override
    public Object call() throws Exception {
        scan(new File("C:/"), 0);
        return null;
    }

    protected void scan(File path, int deepth) {
        if (deepth < 15) {
            System.out.println("Scanning " + path + " at a deepth of " + deepth);

            File[] files = path.listFiles();
            for (File file : files) {
                if (file.isDirectory()) {
                    scan(file, ++deepth);
                }
            }
        }
    }
}

public static class Counter implements Callable<Object> {

    @Override
    public Object call() throws Exception {
        for (int index = 0; index < 1000; index++) {
            Thread.sleep(1);
            System.out.println(index);
        }
        return null;
    }
}
_

それを実行します...

ここで、ExecutorService service = Executors.newFixedThreadPool(2);ExecutorService service = Executors.newFixedThreadPool(1);に変更して、再度実行します。違いがわかりましたか?

これは、エグゼキュータがキューの処理中に同時に使用できるスレッドの数を制御する方法です。

さらにいくつかのタスクを作成し、それらをキューに追加して、何が得られるかを確認します。

33
MadProgrammer

マルチスレッドを使用して複数のフォルダー内のファイルを検索するユースケースがありました。入力として、ルートディレクトリパスしかなく、子ディレクトリはいくつあってもかまいません。仮定-ファイルは常に子ディレクトリの1つでのみ使用できます。

import Java.io.File;
import Java.io.FileFilter;
import Java.util.concurrent.ExecutorService;
import Java.util.concurrent.Executors;

public class SearchFile implements Runnable {

    private String dirPath = null;

    public SearchFile() {

    }

    public SearchFile(String dirPath) {
        this.dirPath = dirPath;
    }

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        File dir = new File("D://");
        checkRootDirectory(dir);
        long endTime = System.currentTimeMillis();
        System.out.println("Time taken: "+(endTime - startTime) + "ms");
    }

    private static void checkRootDirectory(File root) {
        File[] list = root.listFiles(new FileFilter() {

            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory() && !pathname.isHidden();
            }
        });

        ExecutorService service = Executors.newFixedThreadPool(list.length);
        for (File directories : list) {
            String dirPath = directories.getAbsolutePath();
            Thread thread = new Thread(new SearchFile(dirPath));
            service.execute(thread);
        }
        service.shutdown();
        while(!service.isTerminated()) {

        }
    }

    @Override
    public void run() {
        checkEachDirectory(new File(dirPath), "Temp.txt");
    }

    private void checkEachDirectory(File root, String fileName) {
        File[] list = root.listFiles();
        if (null != list) {
            for (File dir : list) {
                if (dir.isDirectory()) {
                    checkEachDirectory(dir, fileName);
                } else if (fileName.equalsIgnoreCase(dir.getName())) {
                    System.out.println(
                            "Thread name: " + Thread.currentThread().getName() + " Founded @" + dir.getAbsolutePath());
                }
            }
        }
    }
}
1
Gopal Aggarwal