给定三个线程 1-3 打印一个字母 AC,我如何保证输出顺序?
我希望线程的输出是“ABCABCABC”
线程独立运行,因此除非您执行特殊的工作来同步线程,否则您永远不会得到这样的输出。预计独立运行的 3 个线程将打印“随机”输出,因为由操作系统来安排线程。
这可能不是线程应该做的,但可以通过简单地使用 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();
}
}
}
我的解决方案在这里:https ://gist.github.com/sinujohn/5fa717dfff680634c6b0c2a7eca108ac可以修改来实现这一点。这个想法是创建一个保存状态的对象并在所有线程之间共享该对象。只有一个同步块可以访问共享状态对象。
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,这可能会对您有所帮助。
您可以使用等待和通知进行线程间通信。我在这里使用 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();
}
}
}
CountDownLatch
您可以通过组合和来实现这一点CyclicBarrier
。这是示例代码:
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();
}
}
}
}
}
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());
}
}
}
一个 Executor,它提供了管理终止的方法和可以生成 Future 以跟踪一个或多个异步任务的进度的方法。
可以关闭 ExecutorService,这将导致它拒绝新任务。提供了两种不同的方法来关闭 ExecutorService。shutdown() 方法将允许先前提交的任务在终止之前执行,而 shutdownNow() 方法阻止等待的任务启动并尝试停止当前正在执行的任务。终止后,执行者没有正在执行的任务,没有等待执行的任务,也没有新的任务可以提交。应关闭未使用的 ExecutorService 以允许回收其资源。
方法 submit 通过创建和返回可用于取消执行和/或等待完成的 Future 扩展了基本方法 Executor.execute(java.lang.Runnable)。方法 invokeAny 和 invokeAll 执行最常用的批量执行形式,执行一组任务,然后等待至少一个或全部完成。(类 ExecutorCompletionService 可用于编写这些方法的自定义变体。)
Executors 类为此包中提供的执行器服务提供工厂方法。