Communication between Java threads (wait() in Object, join() in Thread, await()/countDown() in CountDownLatch, await() in CyclicBarrier)

Multiple threads work together to complete a task, involving inter-thread communication

How to make two threads execute at the same time?

private static void demo1(){<!-- -->

Thread A = new Thread(new Runnable(){<!-- -->
@Override
public void run(){<!-- -->
printlNumber("A");
}
});

Thread B = new Thread(new Runnable(){<!-- -->
@Override
public void run(){<!-- -->
printNumber("B");
}
});

A.start();
B.start();
}
private static void printNumber(String threadName) {<!-- -->
    int i=0;
    while (i + + < 3) {<!-- -->
        try {<!-- -->
            Thread.sleep(100);
        } catch (InterruptedException e) {<!-- -->
            e.printStackTrace();
        }
        System.out.println(threadName + " print: " + i);
    }
}

How to make two threads run across each other in a specified order?

/**
After A prints 1, B prints 1, 2, 3
A continues to print 2, 3

A 1, B 1, B 2, B 3, A 2, A 3
\t
Use the two methods Object.wait() and Object.notify() to execute
*/
private static void demo(){<!-- -->
\t
Object lock = new Object();

Thread A = new Thread(new Runnable(){<!-- -->
@Override
public void run(){<!-- -->
\t\t
synchronized(lock){<!-- -->
System.out.println("A 1");
try{<!-- -->
lock.wait();
} catch (InterruptedException e) {<!-- -->
                    e.printStackTrace();
                }

System.out.println("A 2");
                System.out.println("A 3");
}
}
});

Thread B = new Thread(new Runnable(){<!-- -->
@Override
public void run(){<!-- -->
\t\t\t
synchronized(lock){<!-- -->
System.out.println("B 1");
                System.out.println("B 2");
                System.out.println("B 3");
                lock.notify();
}
}
});
A.start();
B.start();
}

Four threads A B C D, among which D will not be executed until A B C is completed, and A B C runs synchronously

/**
B starts printing after A has finished printing, using thread.join()
*/
private static void demo(){<!-- -->
\t
Thread A = new Thread(new Runnable{<!-- -->
\t\t
@Override
public void run(){<!-- -->
printNumber("A");
}
});

Thread B = new Thread(new Runnable(){<!-- -->
\t\t
@Override
public void run(){<!-- -->
System.out.println("B starts waiting for A");
try{<!-- -->
A.join();
}catch(InterruptedException e){<!-- -->
e.printStackTrace();
}
printNumber("B");
}
});

B.start();
A.start();
}

/**
Three threads A B C run at the same time, and each thread notifies D after running independently; for D, as long as A B C has finished running, D will start running again.
CountedownLatch implementation
*/
private static void runDAfterABC(){<!-- -->
\t
int worker = 3;
CountDownLatch countDownLatch = new CountDownLatch(worker); //Create a counter with an initial value of 3

new Thread(new Runnable(){<!-- -->
\t\t
@Override
public void run(){<!-- -->
\t\t
System.out.println("D is waiting for other three threads");
try{<!-- -->
//D thread enters the waiting state until the count value becomes 0
countDownLatch.await("All done, D starts working");
System.out.println();
}catch(InterruptedException e){<!-- -->
e.printStackTrace();
}
}
}).start();

for(char threadName='A';threadName <='C';threadName + + ){<!-- -->
final String tN = String.valueOf(threadName);
new Thread(new Runnable(){<!-- -->
\t\t\t
@Override
public void run(){<!-- -->
System.out.println(tN + " is working");
try{<!-- -->
Thread.sleep(100);
}catch(Excption e){<!-- -->
e.printStackTrace();
}
System.out.prinltn(tN + "finished");
//Called by other threads, this method decrements the count value by 1 until it reaches 0, and waits for the thread to continue executing.
countDownLatch.countDown();
}
}).start();
}
}

The three athletes prepare separately, and then run together when all three are ready

The CountDownLatch above can be used to count down, but when the count is completed, only one thread’s await() will receive a response, and multiple threads cannot be triggered at the same time.

private static void runABCWhenAllReady(){<!-- -->
\t
//Create a public CyclicBarrier object and set the number of threads waiting at the same time to 3
int runner = 3;
CyclicBarrier cyclicBarrier = new CyclicBarrier(runner);

final Random random = new Random();
for(char runnerName='A';runnerName<='C';runnerName + + ){<!-- -->
final String rN = String.valueOf(runnerName);
\t\t
new Thread(new Runnable(){<!-- -->
\t\t
long prepareTime = random.nextInt(10000) + 100;
System.out.println(rN + " is preparing for time: " + prepareTime);
try{<!-- -->
Thread.sleep(prepareTime);
}catch(Exception e){<!-- -->
e.printStackTrace();
}

try{<!-- -->
System.out.println(rN + " is prepared, waiting for others");
                cyclicBarrier.await(); // The current athlete is ready and waits for others to be ready
}catch(InterruptedException e){<!-- -->
e.printStackTrace();
}catch (BrokenBarrierException e) {<!-- -->
                e.printStackTrace();
            }
            System.out.println(rN + " starts running"); // All athletes are ready and start running together
}).start();
}
}

After the sub-thread completes a certain task, it returns the result to the main thread

FutureTask is used with Callable, and the get method will block the main thread.

/**
The child thread calculates the addition from 1 to 100 and returns the calculated result to the main thread.
*/
private static void doTaskWithResultInWorker(){<!-- -->
\t
Callable<Integer> callable = new Callable<Integer>(){<!-- -->
\t\t
@Override
public Integer call() throws Exception{<!-- -->
\t\t\t
System.out.println("Task starts");
            Thread.sleep(1000);
            int result = 0;
            for (int i=0; i<=100; i + + ) {<!-- -->
                result + = i;
            }
            System.out.println("Task finished and return result");
            return result;
}
};

FutureTask<Integer> futureTask = new FutureTask<>(callable);
new Thread(futureTask).start();

try{<!-- -->
System.out.println("Before futureTask.get()");
        System.out.println("Result: " + futureTask.get()); //The main thread blocks the main thread when calling the futureTask.get() method
        System.out.println("After futureTask.get()");
} catch (InterruptedException e) {<!-- -->
        e.printStackTrace();
    } catch (ExecutionException e) {<!-- -->
        e.printStackTrace();
    }
}