Suppose I now have three strings, abcdefg, 1234567,!@#$%^&, I expect to use multithreading for printing, the result is a1! b2@c3 #d4$e5%f6^g7&. This is also an interview question.
There are three scenarios, synchronized,ReentrantLock with Condition, Park of LockSupport, and unpark.
The idea for this question is what to do, use multithreading, and control the execution order of the execution threads to finish printing the results.
To control the order in which threads execute, you must use the thread's communication mechanism.
Synchronized Mode
This mechanism can be accomplished in synhronized with the wait() and notify,notifyAll methods in the lock object. However, notify can only wake up a random thread, which is definitely not useful. NotfyAll wakes all currently locked wait threads, so in order for the wake threads to be executed as I want, a conditional state is required to control them. For instance.
For example, you now define a member variable shared by threads that has three states, 0, 1, 2, and three threads A,B,C to execute data for each of these three states. My idea now is that when A is finished, B is executed, then C is executed, and then this closed-loop operation of A is executed until the final execution is completed. Then this variable, with an initial value of 0, lets it enter my A thread. After executing the operation of the A thread, set the variable to 1, call the notifyAll method, wake up the B,C threads. At this time, the B,C threads determine if the variable meets their own execution conditions, B finds that it meets, and then proceeds to the following method. C finds that it is not satisfied and continues to call the wait method to block.
Lock+Condition mode
Unlike Conditions, ReentrantLock can contain multiple Conditions, similar to the waitSet in Synchronized. Then there is such a way of thinking. There are now threads A, B, and C that poll for execution of three strings. So I can also define three conditions, which are await blocked by default. In the main thread, I first use the signal method to wake up the configuration corresponding to thread A, execute the business logic of A, complete the business logic execution of A, wake up the Condition of B in thread A, and then the B thread starts execution. Then, after B's business execution is complete, wake up the signal method in C's Condition. Execute in turn until program execution is complete.
park,unpark in LockSupport
This is similar to Lock+Condition. Lock+Condition wakes up the only thread in Condition, and park,unpark operates directly on the thread. However, there is a problem during execution. When using unpark (thread name) to wake up a thread, the thread is empty, which needs to be well understood later.
Code
package com.bo.threadstudy.four; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.ReentrantLock; @Slf4j public class ThreadPrintDataTest { //Multi-threaded Print Alternating Data Problem private static String a = "abcdefg"; private static String b = "1234567"; private static String c = "!@#$%^&"; /** * Using Synchronized to Solve Print Data Interlacing */ @Test public void synchronizedTest() throws InterruptedException { Object lock = new Object(); char[] aArr = a.toCharArray(); char[] bArr = b.toCharArray(); char[] cArr = c.toCharArray(); //What to do with this scheme? Set a status, after a printing is completed, the status is set to b, after B printing is completed, the status is set to c, after C printing is completed, the status is set to a //Status set to 0,1,2 new Thread(() -> { for (int i = 0; i < aArr.length; i++) { printSynchronized(aArr, 0, i, lock); } }, "t1").start(); new Thread(() -> { for (int i = 0; i < aArr.length; i++) { printSynchronized(bArr, 1, i, lock); } }, "t2").start(); new Thread(() -> { for (int i = 0; i < aArr.length; i++) { printSynchronized(cArr, 2, i, lock); } }, "t3").start(); while (true) { Thread.sleep(1000); } } private volatile Integer status = 0; /** * synchronized Polling Print Status * * @param arr array * @param curStatus current state * @param index index subscript * @param lock Locks used */ private void printSynchronized(char[] arr, int curStatus, int index, Object lock) { //Status should be public synchronized (lock) { //Unequal state, blocked first while (curStatus != status) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //Equal state System.out.print(arr[index]); if (status == 2) { status = 0; } else { status++; } lock.notifyAll(); } } /** * Use Lock with Condition for use */ @Test public void lockConditionTest() throws InterruptedException { //The idea is that there are multiple conditions under a Lock name, and different elements are put into different conditions to complete the operation. ReentrantLock lock = new ReentrantLock(); Condition condition1 = lock.newCondition(); Condition condition2 = lock.newCondition(); Condition condition3 = lock.newCondition(); char[] aArr = a.toCharArray(); char[] bArr = b.toCharArray(); char[] cArr = c.toCharArray(); Thread t1 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < aArr.length; i++) { printCondition(condition1, condition2, aArr, i, lock); } } }, "t1"); t1.start(); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < aArr.length; i++) { //The waitSet holds the thread ID, which should also be the thread ID. It must hold only one thread ID. printCondition(condition2, condition3, bArr, i, lock); } } }, "t2").start(); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < aArr.length; i++) { printCondition(condition3, condition1, cArr, i, lock); } } }, "t3").start(); //Conditions and locks appear to be similar to synchronized calls and must be accessed in the lock method, as you can see lock.lock(); try { condition1.signal(); } finally { lock.unlock(); } Thread.sleep(100000); } //The object-oriented writing by the teacher is better than that by me. I don't have an object-oriented idea, but I have the right one. private void printCondition(Condition curCondition, Condition nextCondition, char[] arr, int index, ReentrantLock lock) { lock.lock(); try { //Current Condition is waiting curCondition.await(); System.out.print(arr[index]); nextCondition.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } /** * LockSupport-based park,unpark mechanism to complete */ static Thread t1; static Thread t2; static Thread t3; public static void main(String[] args) { ReentrantLock lock = new ReentrantLock(); char[] aArr = a.toCharArray(); char[] bArr = b.toCharArray(); char[] cArr = c.toCharArray(); //Initially, they are suspended. External control is used to release them. Is the teacher's encapsulation mainly for the thread to initialize? //There is a problem with this writing, that is, waking up when the thread object is undefined, which is incorrect t1 = new Thread(new Runnable() { @Override public void run() { for (char c1 : aArr) { lockSupportPrint(c1,lock, Thread.currentThread(), t2); } } }); t2 = new Thread(new Runnable() { @Override public void run() { for (char c1 : bArr) { lockSupportPrint(c1,lock, Thread.currentThread(), t3); } } }); t3 = new Thread(new Runnable() { @Override public void run() { for (char c1 : cArr) { lockSupportPrint(c1,lock,Thread.currentThread(), t1); } } }); //Thread Start Order Issue //TODO has a problem here. Thread variables must be defined as static variables, start() startup must be placed behind, or incoming Thread objects may be empty. //Go to see what's wrong later on t1.start(); t2.start(); t3.start(); LockSupport.unpark(t1); } //No locks needed. Writing confused private static void lockSupportPrint(char value, ReentrantLock lock, Thread curThread, Thread nextThread){ //Pause the current thread LockSupport.park(); System.out.print(value); //Wake up the next thread LockSupport.unpark(nextThread); } }
Finally, the fourth day of the course is finished, come down to prepare the fifth day of the course, except for the eighth day, there is not much left. Go on, as soon as possible.