简体   繁体   English

如何确保 Java 线程按特定顺序运行

[英]How to ensure Java threads run in a particular order

Given three threads, 1-3, that print a letter, AC, how can I guarantee the output order?给定三个线程,1-3,打印一个字母 AC,我如何保证输出顺序?

I would like the output of the threads to be "ABCABCABC"我希望线程的输出为“ABCABCABC”

Threads run independently, so you will never get such output unless you perform special efforts to synchronize your threads.线程独立运行,因此除非您特别努力同步线程,否则您永远不会获得此类输出。 3 threads that are running independently are expected to print "random" output because it is up to OS to schedule the threads.预计 3 个独立运行的线程会打印“随机”输出,因为由操作系统来调度线程。

This may not be what threads supposed to do but, it can be achieved by simply using join (which asks the start ING thread to wait for the completion of the start ED thread.这可能不是线程应该做的,但是可以通过简单地使用 join 来实现(它要求开始ING线程等待开始ED线程的完成。

class A implements Runnable {

@Override
public void run() {
    try {
        Thread.sleep(12);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("ClassA : A");
}

}

class B implements Runnable {

@Override
public void run() {
    try {
        Thread.sleep(12);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("ClassB : B");
}

}

class C implements Runnable {

@Override
public void run() {
    try {
        Thread.sleep(12);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("ClassC : C");
}

}

public class OrderedThreadApp {
public static void main(String[] args) {

    Thread a = new Thread(new A());
    Thread b = new Thread(new B());
    Thread c = new Thread(new C());

    a.start();
    try {
        a.join();
        b.start();
        b.join();
        c.start();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
}

My solution over here: https://gist.github.com/sinujohn/5fa717dfff680634c6b0c2a7eca108ac can be modified to achieve this.我的解决方案在这里: https : //gist.github.com/sinujohn/5fa717dfff680634c6b0c2a7eca108ac可以修改来实现这一点。 The idea is to create an object which holds the state and share that object among all the threads.这个想法是创建一个保存状态的对象并在所有线程之间共享该对象。 There is only one synchronized block to access the shared state object.只有一个同步块可以访问共享状态对象。

public class Main {

    public static void main(String[] args) throws InterruptedException {
        MyState state = new MyState();

        final Thread t1 = new Thread(new MyRunnable(10, 'A', state));
        final Thread t2 = new Thread(new MyRunnable(10, 'B', state));
        final Thread t3 = new Thread(new MyRunnable(10, 'C', state));
        t1.start();
        t2.start();
        t3.start();
    }
}

class MyState {
    private char state = 'A';

    public char getState() {
        return state;
    }

    public void incrState() {
        switch(state) {
        case 'A':
            state = 'B';
            return;
        case 'B':
            state = 'C';
            return;
        default:
            state = 'A';
        }
    }
}

class MyRunnable implements Runnable {

    private final int max;
    private final char value;
    private final MyState state;

    MyRunnable(int max, char value, MyState state) {
        this.max = max;
        this.value = value;
        this.state = state;
    }

    @Override
    public void run() {
        int count = 0;
        while(count < max) {
            synchronized (this.state) {
                if (this.state.getState() == this.value) {
                    System.out.print(value);
                    count++;
                    this.state.incrState();
                }
            }
        }
    }
}

检查CyclicBarrier ,这可能对您有所帮助。

You can achieve this by combining CountDownLatch and CyclicBarrier .您可以通过组合CountDownLatchCyclicBarrier来实现这一点。 Here is the sample code:这是示例代码:

    package org.orange.didxga;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

public class ThreadExecutionOrder {

    private CountDownLatch countDownLatch = new CountDownLatch(2);
    private CountDownLatch countDownLatch1 = new CountDownLatch(1);
    private CyclicBarrier barrier;
    private final Object monitor = new Object();

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new ThreadExecutionOrder().test();
    }

    public void test() {
        Runnable t1 = new Runnable() {

            @Override
            public void run() {
                System.out.print("A");
                countDownLatch1.countDown();
                countDownLatch.countDown();
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }

        };
        Runnable t2 = new Runnable() {

            @Override
            public void run() {
                try {
                    countDownLatch1.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.print("B");
                countDownLatch.countDown();
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }

        };
        Runnable t3 = new Runnable() {

            @Override
            public void run() {
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.print("C");
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }

        };
        for(int i=0; i<3; i++) {
            barrier = new CyclicBarrier(3, new Runnable()  {
                @Override
                public void run() {
                    synchronized (monitor) {
                        countDownLatch = new CountDownLatch(2);
                        countDownLatch1 = new CountDownLatch(1);
                        monitor.notify();
                    }
                }

            });
            new Thread(t1).start();
            new Thread(t2).start();
            new Thread(t3).start();
            synchronized (monitor) {
                try {
                    monitor.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

You can use wait and notify for interthread communication.您可以使用 wait 和 notify 进行线程间通信。 I am using turn int variable here for signaling among threads.我在这里使用 turn int 变量在线程之间发送信号。

public class ThreadInterleaving{
    public static void main(String[] args){

    MyThread h = new MyThread();

    Thread t1 = new Thread(h);
    Thread t2 = new Thread(h);
    Thread t3 = new Thread(h);

    t1.start();
    t2.start();
    t3.start();

    }
}

class MyThread implements Runnable{
    public static int turn;

    @Override
    public void run(){
        for(int i =0;i<3;i++){
            synchronized(this){
                if(turn == 0){
                    System.out.println("Thread1");
                    turn =1 ;
                    notify();
                }else{
                    try{
                        wait();
                    }catch(InterruptedException ie){

                    }
                }

                if(turn == 1){
                    System.out.println("Thread2");
                    turn = 2;
                    notify();
                }else{
                    try{
                        wait();
                    }catch(InterruptedException ie){

                    }
                }

                if(turn == 2){
                    System.out.println("Thread3");
                    System.out.println("*********");
                    turn = 0;
                    notify();
                }else{
                    try{
                        wait();
                    }catch(InterruptedException ie){        

                    }
                }
            }
        }
    }
}

/*Output
Thread1
Thread2
Thread3
*********
Thread1
Thread2
Thread3
*********
Thread1
Thread2
Thread3
*********
Thread1
Thread2
Thread3
*********
Thread1
Thread2
Thread3
*********
Thread1
Thread2
Thread3
*********
Thread1
Thread2
Thread3
*********
Thread1
Thread2
Thread3
*********
Thread1
Thread2
Thread3
*********
*/
public class RunningThreadSequentially {
    //Runnable task for each thread
    private static class Task implements Runnable {
        public static int counter=0;

        @Override
        public void run() {
            try {
                synchronized(this) {
                    Thread.sleep(500);
                    System.out.println(Thread.currentThread().getName() + " is completed--" + counter ++);             
                }
            } catch (Exception ex) {
            } 
        }
    }

    public static void main(String args[]) throws InterruptedException {
        while(true) {
            Thread t1 = new Thread(new Task(), "Thread 1");
            Thread t2 = new Thread(new Task(), "Thread 2");
            Thread t3 = new Thread(new Task(), "Thread 3");
            Thread t4 = new Thread(new Task(), "Thread 4");
            Thread t5 = new Thread(new Task(), "Thread 5");
            Thread t6 = new Thread(new Task(), "Thread 6");

            t1.start();
            t1.join();
            t2.start();
            t2.join();
            t3.start(); 
            t3.join(); 
            t4.start(); 
            t4.join(); 
            t5.start();
            t5.join(); 
            t6.start(); 
            t6.join();
        }
    }
}
public class ThreadOrderTest {

int status = 1;

public static void main(String[] args) {
    ThreadOrderTest threadOrderTest = new ThreadOrderTest();
    A a = new A(threadOrderTest);
    B b = new B(threadOrderTest);
    C c = new C(threadOrderTest);
    a.start();
    b.start();
    c.start();
}
}

class A extends Thread {

ThreadOrderTest threadOrderTest;

A(ThreadOrderTest threadOrderTest) {
    this.threadOrderTest = threadOrderTest;
}

@Override
public void run() {
    try {
        synchronized (threadOrderTest) {
            for (int i = 0; i < 10; i++) {
                while (threadOrderTest.status != 1) {
                    threadOrderTest.wait();
                }
                System.out.print("A ");
                threadOrderTest.status = 2;
                threadOrderTest.notifyAll();
            }
        }
    } catch (Exception e) {
        System.out.println("Exception 1 :" + e.getMessage());
    }
}
}

class B extends Thread {

ThreadOrderTest threadOrderTest;

B(ThreadOrderTest threadOrderTest) {
    this.threadOrderTest = threadOrderTest;
}

@Override
public void run() {
    try {
        synchronized (threadOrderTest) {
            for (int i = 0; i < 10; i++) {
                while (threadOrderTest.status != 2) {
                    threadOrderTest.wait();
                }
                System.out.print("B ");
                threadOrderTest.status = 3;
                threadOrderTest.notifyAll();
            }
        }
    } catch (Exception e) {
        System.out.println("Exception 2 :" + e.getMessage());
    }
}
}

class C extends Thread {

ThreadOrderTest threadOrderTest;

C(ThreadOrderTest threadOrderTest) {
    this.threadOrderTest = threadOrderTest;
}

@Override
public void run() {
    try {
        synchronized (threadOrderTest) {
            for (int i = 0; i < 10; i++) {
                while (threadOrderTest.status != 3) {
                    threadOrderTest.wait();
                }
                System.out.println("C ");
                threadOrderTest.status = 1;
                threadOrderTest.notifyAll();
            }
        }
    } catch (Exception e) {
        System.out.println("Exception 3 :" + e.getMessage());
    }
}
}

ExecutorService 执行者服务

An Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks.一个 Executor 提供管理终止的方法和可以生成 Future 以跟踪一个或多个异步任务的进度的方法。

An ExecutorService can be shut down, which will cause it to reject new tasks. ExecutorService 可以关闭,这将导致它拒绝新任务。 Two different methods are provided for shutting down an ExecutorService.提供了两种不同的方法来关闭 ExecutorService。 The shutdown() method will allow previously submitted tasks to execute before terminating, while the shutdownNow() method prevents waiting tasks from starting and attempts to stop currently executing tasks. shutdown() 方法将允许先前提交的任务在终止之前执行,而 shutdownNow() 方法阻止等待任务开始并尝试停止当前正在执行的任务。 Upon termination, an executor has no tasks actively executing, no tasks awaiting execution, and no new tasks can be submitted.终止时,执行器没有正在执行的任务,没有等待执行的任务,也没有新的任务可以提交。 An unused ExecutorService should be shut down to allow reclamation of its resources.应关闭未使用的 ExecutorService 以允许回收其资源。

Method submit extends base method Executor.execute(java.lang.Runnable) by creating and returning a Future that can be used to cancel execution and/or wait for completion.方法 submit 通过创建和返回可用于取消执行和/或等待完成的 Future 来扩展基本方法 Executor.execute(java.lang.Runnable)。 Methods invokeAny and invokeAll perform the most commonly useful forms of bulk execution, executing a collection of tasks and then waiting for at least one, or all, to complete.方法 invokeAny 和 invokeAll 执行最常用的批量执行形式,执行一组任务,然后等待至少一个或全部完成。 (Class ExecutorCompletionService can be used to write customized variants of these methods.) (类 ExecutorCompletionService 可用于编写这些方法的自定义变体。)

The Executors class provides factory methods for the executor services provided in this package. Executors 类为此包中提供的执行程序服务提供了工厂方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM